V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
LinJunzhu
V2EX  ›  问与答

服务器响应 json 字符串的两种格式,有点蒙圈

  •  
  •   LinJunzhu · 2016-05-10 17:53:19 +08:00 · 3165 次点击
    这是一个创建于 3104 天前的主题,其中的信息可能已经有所发展或是发生改变。

    1 、别家的服务器返回数据,在 Chrome 中的 response 查看为:

    {"message":"查询成功","data": "yo"}
    

    2 、有人的服务器返回是:

    "{\"rateInfos\":[]}"
    

    第一种就直接是 json 对象了,第二种是字符串,为什么呢?按道理 http 传输过程中,数据应该都是字符串,为何第一种可以直接为 json 对象了呢?

    查看了下,两者的 response header 都有: Content-Type: application/json

    有点蒙圈,求解答

    第 1 条附言  ·  2016-05-11 11:53:50 +08:00

    通过不断 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\"}" 
    
    
    13 条回复    2016-05-11 11:52:57 +08:00
    bdbai
        1
    bdbai  
       2016-05-10 18:19:15 +08:00 via Android
    第一种看起来正常一点,第二种是直接拿去 eval 了吧。
    wesley
        2
    wesley  
       2016-05-10 18:25:45 +08:00
    没啥好蒙的, 把第二个的开发人员拖出来弹 JJ 1000 遍
    learnshare
        3
    learnshare  
       2016-05-10 18:25:52 +08:00
    第二种错了,那只是字符串。问题出在后端, content-type 和内容不一致。
    just1
        4
    just1  
       2016-05-10 18:30:20 +08:00 via Android
    第二个代码写错了吧
    JiShuTui
        5
    JiShuTui  
       2016-05-10 18:33:21 +08:00
    下面这种情况是可以的
    {"message":"查询成功","data": "yo","data2":"{\"rateInfos\":[]}"}
    miyuki
        6
    miyuki  
       2016-05-10 19:36:12 +08:00 via Android
    正常人写的的都是第一种
    Pure88
        7
    Pure88  
       2016-05-10 22:11:57 +08:00
    @wesley 上下左右各弹 250 遍?
    murmur
        8
    murmur  
       2016-05-10 22:35:13 +08:00
    第二个如果没有 jsonp 的 callback 直接拉出去打
    sensui7
        9
    sensui7  
       2016-05-10 22:59:37 +08:00
    网络丄传输的都是字符串, 这是肯定的, 区别就是一种字符串包含的是 json 编码,楼猪第一个就是这种字符串,
    另一种是普通字符串, 你的第二个 , 只不过这是手动写成了 json 格式了. 相当于 手动版 json_encode
    LinJunzhu
        10
    LinJunzhu  
    OP
       2016-05-10 23:21:27 +08:00
    唔,我想了下:

    第一种,是因为服务器返回了 json 对象,并且服务器语言有相应的序列化 json 接口,在传输时会将 json 对象序列化,浏览器或语言 接收到该响应时,根据 content_type 去反序列解析响应,所以会直接拿到 json 对象。

    第二种,是因为浏览器返回的就是 json 字符串,所以客户端拿到的响应当然仅仅只是字符串了。

    不知道对不对呢?
    LinJunzhu
        11
    LinJunzhu  
    OP
       2016-05-10 23:24:46 +08:00
    @sensui7 感谢,不过我有个疑问,客户端是如何知道这个这个字符串是 json 编码并且进行反序列化呢?。 因为第二种 json 字符串,也符合 json 规范,也是可以进行 parse 操作的呀?
    congeec
        12
    congeec  
       2016-05-10 23:35:53 +08:00   ❤️ 1
    打死也不能 eval() !!!!
    用 JSON.parse()
    LinJunzhu
        13
    LinJunzhu  
    OP
       2016-05-11 11:52:57 +08:00
    通过不断 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\"}"

    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2212 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 479ms · UTC 16:11 · PVG 00:11 · LAX 08:11 · JFK 11:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.