在往js传封装的json的时候,我这里用了四种处理方式,前三种都是在data后面包含了一个字符串,第四种包含的是一个对象。
传递的json数据格式:
{
"data" : "{包含的数据}"
}
这三种方法不同的地方在于这个 ”包含的数据“ 的不同
在js的代码中,在接受oc传过来的数据之后,调用的方法是
//将 result(从OC传到JS中的json字符串)转为json对象
var msg = JSON.parse(result);
console.info("JSON:" + msg);
那么问题来了......
在这四种方法中,我在OC封装的JSON数据都是可以在线解析的,数据格式正确。
区别是:前三种方法中 data 对应的 value 是字符串,第四种是对象。到了JS这边就只有第四种接收正确了,可以被正确解析,前三种的JSON数据都报错,在JS代码中执行到var msg = JSON.parse(result);
这个方法就卡死了。
oc封装:(获取的定位信息)
第一种情况:(直接将字典对象转为字符串,然后没有去掉 空格 和 换行 字符)
先将这个数据(字典对象)转为字符串:
{\ncity=\"\\U5e7f\\U5dde\\U5e02\";\ncitycode=020;\nlatitude=nil;\nlongitude=nil;\nresult=fail;\n}
封装之后的数据:
{
"data": "{\ncity=\"\\U5e7f\\U5dde\\U5e02\";\ncitycode=020;\nlatitude=nil;\nlongitude=nil;\nresult=fail;\n}",
"callbackid": "9cf324f8-7606-ab8a-74e6-8902c75ec816"
}
然后传给js
js接受的数据格式:(在线解析不了)
{"data":"{
city="\U5e7f\U5dde\U5e02";
citycode=020;
latitude=nil;
longitude=nil;
result=fail;
}","callbackid":"43887cdf-2b10-e5e9-1f59-921fbbf60723"}
第二种情况:(在第一种的情况下多加了一个步骤:去除空格和换行)
封装之后的数据:
{
"data": "{\"citycode\":\"020\",\"result\":\"fail\",\"latitude\":\"nil\",\"longitude\":\"nil\",\"city\":\"广州市\"}",
"callbackid": "0679b5ae-2e79-2dde-01db-1db3df484542"
}
js接收之后的数据格式:(在线解析不了)
{
"data": "{"citycode":"020","result":"fail","latitude":"nil","longitude":"nil","city":"广州市"}",
"callbackid": "1f96fbab-239f-811e-e8f7-4ce877e71bea"
}
第三种情况:(增加了将 双引号 “ 替换成 单引号 ‘ 的方法)(安卓传JS时的数据格式就是这种)
封装之后的数据:
{
"data": "{'citycode':'020','result':'fail','latitude':'nil','longitude':'nil','city':'广州市'}",
"callbackid": "13e85ae2-d3b7-81ac-a91b-17465b77f820"
}
但是这个数据格式当做参数传给JS的时候,OC调用JS的方法不成功,JS接受不到OC传递的数据。
第四种情况就是(增加一个方法,将
"citycode":"020","result":"fail","latitude":"nil","longitude":"nil","city":"广州市"
}
)这个数据当做一个对象来处理,即NSDictionary对象,而不是一个String。
然后封装完的数据是:
{
"data": {
"citycode": "020",
"result": "fail",
"latitude": "nil",
"longitude": "nil",
"city": "广州市"
},
"callbackid": "2e8f6b8f-1da5-5da5-ba45-1c215d095320"
}
传给js之后接受的数据格式:
{
"data": {
"citycode": "020",
"result": "fail",
"latitude": "nil",
"longitude": "nil",
"city": "广州市"
},
"callbackid": "2e8f6b8f-1da5-5da5-ba45-1c215d095320"
}
这四种情况,唯独最后一种是可行的。
安卓的传递之前的数据格式:
{
"callbackid":"4c745e8a-2d9b-5f17-756e-1b31054ff384",
"data":"{\u0027apnType\u0027:\u0027wifi\u0027,\u0027deviceManufacturer\u0027:\u0027Xiaomi\u0027,\u0027deviceModel\u0027:\u0027MI 4LTE\u0027,\u0027deviceOperatorName\u0027:\u0027中国联通\u0027,\u0027iMei\u0027:\u0027865931025442476\u0027,\u0027systemVersion\u0027:\u00274.4.4\u0027,\u0027restDiskSize\u0027:\u0027721 MB\u0027,\u0027isPad\u0027:false}"
}
安卓的JS接受之后的数据格式:
{
"callbackid": "4c745e8a-2d9b-5f17-756e-1b31054ff384",
"data": "{'apnType':'wifi','deviceManufacturer':'Xiaomi','deviceModel':'MI 4LTE','deviceOperatorName':'中国联通','iMei':'865931025442476','systemVersion':'4.4.4','restDiskSize':'721 MB','isPad':false}"
}
其实我在这里已经可以解决 往JS传递JSON数据的需求了,直接用第四种方法就可以了。
但是
项目
要求
安卓和iOS数据格式要
统一
安卓原生代码封装的JSON数据用的第三种方法中的数据格式,传给JS之后,没有任何变化,原原本本的被JS接受并且解析成功。这个iOS传过去之后就变了数据格式,不能解析了。
我很纳闷是什么原因,于是我怀疑是不是我用的调用JS的方法不对,于是我用了两种方法:
NSString * handlerName = [self jsURlFormat:model.handlerName];
NSString * data = [self jsURlFormat:model.data];
NSString * callback = [self jsURlFormat:model.callback];
NSString *jString = [NSString stringWithFormat:@"jsbridge.receive(%@,%@,%@)",handlerName,data,callback];
JSContext *context = [[CsairWebView shareInstance] valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
[context evaluateScript:jString];
});
[[CsairWebView shareInstance] stringByEvaluatingJavaScriptFromString:self.jString];
我试过这两个方法之后,对与我传给JS的JSON数据,在jS端接受的数据没有任何变化,所以还是只有第四种方法行的通,其他三个没有变化。
然后
我有一个大胆的猜测
苹果在设计这个方法的时候不支持多层JSON数据的时候,最里层的为字符串,而是需要一个对象。
比如这个JSON数据结构中
{
"data" : "{包含的数据}"
}
这个 "{包含的数据}" 不能是字符串 ,必须是对象,也就是这个样子的
{
"data" : {包含的数据}
}
还有一个猜测就是这可能是一个BUG。
最后,我也没解决这个问题,探究不到原理,找了很多资料也找不到为什么。有哪位大神能告诉我一声,我下面是代码的地址,有兴趣的可以下载研究以下。我的QQ:812656410@qq.om