1 、别家的服务器返回数据,在 Chrome 中的 response 查看为:
{"message":"查询成功","data": "yo"}
2 、有人的服务器返回是:
"{\"rateInfos\":[]}"
第一种就直接是 json 对象了,第二种是字符串,为什么呢?按道理 http 传输过程中,数据应该都是字符串,为何第一种可以直接为 json 对象了呢?
查看了下,两者的 response header 都有: Content-Type: application/json
有点蒙圈,求解答
通过不断 google + 实验,我觉得我得到了答案。
首先, response header 内的 content_type 仅仅只是表明响应数据是怎样的数据,并不会自动去解析成 JSON 对象 (注: 有浏览器原生 JSON 对象,其他的都为语言的对象)。
比如原生 AJAX ,拿到该响应,仅仅只是 string 。 而 jQuery 则会根据 content_type 去将响应解析成对应的格式
至于浏览器开发者工具,你看到的 JSON 对象,是浏览器开发者工具为了方便我们开发,自己将它解析成了对应的格式。
接着,当你在服务手动创建:
# Rails
render text: '{"a": "a"}', content_type: "application/json"
此时你在浏览器就会看到问题内的第一种情况,也即正常情况。 浏览器会根据 content_type 将他解析
# Rails
render json: { a: 'a' }
此时, Rails 会自动将他序列化成字符串(即跟手动创建字符串没两样),然后进行传输。
那么,问题第二种情况是怎样的呢?如果服务器仅仅只是返回 JSON 字符串的话,那么肯定也是会自动解析的呀。答案在于服务器的开发人员傻了。
# 正常情况
'{"a": "a"}'
# 而开发人员由于某种原因,将 json 字符串又序列化了一遍
# 类似于这种效果
JSON.stringify(JSON.stringify(jsonObejct))
# 因此最终服务器返回的字符串其实是:
"\"{\\\"a\\\": \\\"a\\\"\}\""
# 浏览器拿到的字符串解析后是:
"{\"a\": \"a\"}"
1
bdbai 2016-05-10 18:19:15 +08:00 via Android
第一种看起来正常一点,第二种是直接拿去 eval 了吧。
|
2
wesley 2016-05-10 18:25:45 +08:00
没啥好蒙的, 把第二个的开发人员拖出来弹 JJ 1000 遍
|
3
learnshare 2016-05-10 18:25:52 +08:00
第二种错了,那只是字符串。问题出在后端, content-type 和内容不一致。
|
4
just1 2016-05-10 18:30:20 +08:00 via Android
第二个代码写错了吧
|
5
JiShuTui 2016-05-10 18:33:21 +08:00
下面这种情况是可以的
{"message":"查询成功","data": "yo","data2":"{\"rateInfos\":[]}"} |
6
miyuki 2016-05-10 19:36:12 +08:00 via Android
正常人写的的都是第一种
|
8
murmur 2016-05-10 22:35:13 +08:00
第二个如果没有 jsonp 的 callback 直接拉出去打
|
9
sensui7 2016-05-10 22:59:37 +08:00
网络丄传输的都是字符串, 这是肯定的, 区别就是一种字符串包含的是 json 编码,楼猪第一个就是这种字符串,
另一种是普通字符串, 你的第二个 , 只不过这是手动写成了 json 格式了. 相当于 手动版 json_encode |
10
LinJunzhu OP 唔,我想了下:
第一种,是因为服务器返回了 json 对象,并且服务器语言有相应的序列化 json 接口,在传输时会将 json 对象序列化,浏览器或语言 接收到该响应时,根据 content_type 去反序列解析响应,所以会直接拿到 json 对象。 第二种,是因为浏览器返回的就是 json 字符串,所以客户端拿到的响应当然仅仅只是字符串了。 不知道对不对呢? |
11
LinJunzhu OP @sensui7 感谢,不过我有个疑问,客户端是如何知道这个这个字符串是 json 编码并且进行反序列化呢?。 因为第二种 json 字符串,也符合 json 规范,也是可以进行 parse 操作的呀?
|
12
congeec 2016-05-10 23:35:53 +08:00 1
打死也不能 eval() !!!!
用 JSON.parse() |
13
LinJunzhu OP 通过不断 google + 实验,我觉得我得到了答案。
首先, response header 内的 content_type 仅仅只是表明响应数据是怎样的数据,并不会自动去解析成 JSON 对象 (注: 有浏览器原生 JSON 对象,其他的都为语言的对象)。 比如原生 AJAX ,拿到该响应,仅仅只是 string 。 而 jQuery 则会根据 content_type 去将响应解析成对应的格式 至于浏览器开发者工具,你看到的 JSON 对象,是浏览器开发者工具为了方便我们开发,自己将它解析成了对应的格式。 接着,当你在服务手动创建: ```ruby # Rails render text: '{"a": "a"}', content_type: "application/json" ``` 此时你在浏览器就会看到问题内的第一种情况,也即正常情况。 浏览器会根据 content_type 将他解析 ```ruby # Rails render json: { a: 'a' } ``` 此时, Rails 会自动将他序列化成字符串(即跟手动创建字符串没两样),然后进行传输。 那么,问题第二种情况是怎样的呢?如果服务器仅仅只是返回 JSON 字符串的话,那么肯定也是会自动解析的呀。答案在于服务器的开发人员傻了。 ```ruby # 正常情况 '{"a": "a"}' # 而开发人员由于某种原因,将 json 字符串又序列化了一遍 # 类似于这种效果 JSON.stringify(JSON.stringify(jsonObejct)) # 因此最终服务器返回的字符串其实是: "\"{\\\"a\\\": \\\"a\\\"\}\"" # 浏览器拿到的字符串解析后是: "{\"a\": \"a\"}" ``` |