• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lagoon
V2EX  ›  程序员

再争论一个 json 转义的问题

  •  
  •   lagoon · Jun 13, 2020 · 7398 views
    This topic created in 2339 days ago, the information mentioned may be changed or developed.
    {\"身份\":\"学生\",\"姓名\":\"张三\"}

    这就是后台给的 json 原文,换种说法,也就是接口拿到的实际数据。嗯...甚至还有带\和不带的混合双打。

    众所周知这是转义,但我目前所知,dart,android 用的 gson,ios 都是无法直接将它转 json 对象的。需要先经过处理,把\去掉。
    但后台,一般觉得这是规范的 json 。


    每次遇到这个问题,都吵的不可开交。

    请大家评理。


    真的心累,不知道实际该怎么看待。因为很常见,我转不了,但后台又非常生气,觉得肯定是没问题。
    Supplement 1  ·  Jun 13, 2020
    因为这个,还和小群里的好友吵的面红耳赤。

    其实我知道出现这种情况,是有一些特殊原因的,还真不能怪后端,前端也不是不能处理。
    只是每次遇到,对方都一副咬定这格式没问题,非常理直气壮。导致我都怀疑是不是我的工具有问题。
    57 replies  •  2020-06-17 17:53:43 +08:00
    lagoon
    lagoon
    OP
    Jun 13, 2020
    1
    顺便一提,js 是可以的。
    msg7086
    msg7086
    Jun 13, 2020
    2
    这不是 JSON 原文,这是把 JSON 又做了一边转义的结果。

    比如
    var a = "{\"身份\":\"学生\",\"姓名\":\"张三\"}"

    a 的内容是什么?
    是 {"身份":"学生","姓名":"张三"}

    上面 var a 后面的是为了把 JSON 表示成字符串而做的一层额外转义。变量内部是没有斜线的。

    所以后台要么给
    "{\"身份\":\"学生\",\"姓名\":\"张三\"}"
    也就是两次序列化,

    要么给
    {"身份":"学生","姓名":"张三"}
    也就是一次序列化。
    also24
    also24
    Jun 13, 2020
    3
    要不要试试先把它当 JSON String 而不是 JSON Object

    https://i.loli.net/2020/06/13/WPlr4MVNJE7XxmZ.png
    lagoon
    lagoon
    OP
    Jun 13, 2020
    4
    @msg7086 但我遇到过的后台哥,全部非常肯定,这就是 json,肯定能转。
    also24
    also24
    Jun 13, 2020
    5
    我的描述好像容易引起歧义,我重洗说一下
    lagoon
    lagoon
    OP
    Jun 13, 2020
    6
    @also24 所以我没敢回复,有点看不懂
    EminemW
    EminemW
    Jun 13, 2020
    7
    你这个是字符串吧。。你把字符串转成 JSON 对象不就好了
    nc4697
    nc4697
    Jun 13, 2020
    8
    这不叫 JSON 。这是 JSON 格式的字符串
    also24
    also24
    Jun 13, 2020
    9
    @lagoon #6
    我的锅,这个专业撞上了 Python 的转义,没能表达出我的意思

    我还是直接写文本吧。

    按道理来说,你可以在这个字符串外面再套一层就好理解了

    {
    "str": "{\"身份\":\"学生\",\"姓名\":\"张三\"}"
    }

    大意如上,服务器返回的内容被当作嵌套了一层 JSON String,这样再拿 str 字段出来的时候,就会处理掉转义了。

    实际上大意和二楼是一致的,只是我不小心举了个错误的例子。
    lagoon
    lagoon
    OP
    Jun 13, 2020
    10
    @also24 我在 dart 和 java 上的体验,拿出来,就是{\"身份\":\"学生\",\"姓名\":\"张三\"},除非自己手动转义。所以尴尬
    kojirou
    kojirou
    Jun 13, 2020
    11
    ?
    let str = """
    {\"身份\":\"学生\",\"姓名\":\"张三\"}
    """
    dump(try JSONSerialization.jsonObject(with: Data(str.utf8), options: []))
    kojirou
    kojirou
    Jun 13, 2020
    12
    不好意思看错了,无视我
    FutherAll
    FutherAll
    Jun 13, 2020 via iPhone
    13
    就是个 JSON string,iOS 可以转
    jorneyr
    jorneyr
    Jun 13, 2020
    14
    把后台给的 JSON 字符串放到 http://json.cn 里试试,如果报错说明不是 JSON 字符串,如果不报错说明正确的 JSON 字符串,可以多试几个这样的工具,用事实解决争论。
    lagoon
    lagoon
    OP
    Jun 13, 2020
    15
    @jorneyr 没用。这招早用过了。
    他们一口咬定可以。
    jorneyr
    jorneyr
    Jun 13, 2020
    16
    @lagoon 那这一家不是正确与否的问题了,而是人的问题
    lagoon
    lagoon
    OP
    Jun 13, 2020
    17
    @jorneyr 但不是一个人,是我遇到的 n 位后台....
    lagoon
    lagoon
    OP
    Jun 13, 2020
    18
    @FutherAll
    我估计你是类似
    var str = "{\"身份\":\"学生\",\"姓名\":\"张三\"}"
    这样去验证的对吧?

    不是的,这样你断点看看 str,\已经被转义了。json 处理时没有\了
    also24
    also24
    Jun 13, 2020
    19
    重新敲了个例子,不知道这样是否好理解点

    https://i.loli.net/2020/06/13/eE1zGyB2M9lUNoX.png
    zhuangzhuang1988
    zhuangzhuang1988
    Jun 13, 2020
    20
    直接 base64 把.
    dasauto
    dasauto
    Jun 13, 2020 via iPhone
    21
    我之前在项目上也碰到过,手动狗头
    lagoon
    lagoon
    OP
    Jun 13, 2020
    22
    @dasauto 真的是很常见。我已经遇到不止一次了。
    crella
    crella
    Jun 13, 2020 via Android
    23
    代码

    # -*- encoding : utf-8 -*-
    require 'json'
    str = '{\"身份\":\"学生\",\"姓名\":\"张三\"}'
    a = JSON.load(str)
    puts a.inspect

    结果报错。
    /usr/local/ruby-2.7.0/lib/ruby/2.7.0/json/common.rb:156:in `parse': 783: unexpected token at '{\\"身份\\":\\"学生\\",\\"姓名\\":\\"张三\\"}' (JSON::ParserError)
    from /usr/local/ruby-2.7.0/lib/ruby/2.7.0/json/common.rb:156:in `parse'
    watzds
    watzds
    Jun 13, 2020 via Android
    24
    可能是后端手写的 json,笑死人了,有些人不知道序列化
    Trim21
    Trim21
    Jun 13, 2020 via Android
    25
    混合双打出来还能正确 decode 吗…
    also24
    also24
    Jun 13, 2020
    26
    @crella #23
    还要处理掉 python 本身对 \ 的转义,所以应该是两个 \
    dasauto
    dasauto
    Jun 13, 2020 via iPhone
    27
    @lagoon
    这种真的是想骂人
    nicebird
    nicebird
    Jun 13, 2020
    28
    难道手写的 json???
    ipwx
    ipwx
    Jun 13, 2020
    29
    这问题还用争论?把这个字符串扔进文本文件,让后端读出来自己用标准 JSON Parser 解析,看看他们行不行。这还能不闭嘴?能解析除非是调用了 eval 。
    ipwx
    ipwx
    Jun 13, 2020
    30
    如果用了 eval 就更简单了,给他们展示一下脚本注入。
    FutherAll
    FutherAll
    Jun 13, 2020
    31
    @lagoon 还真是,默认转义了\
    不过我还是没理解,从接口拿到的数据是啥格式的,var str = "{\"身份\":\"学生\",\"姓名\":\"张三\"}"
    这种默认转移掉不是可以解析么,是带了两个\\么
    maobukui
    maobukui
    Jun 13, 2020
    32
    转义的目的为了防止语法上的歧义。
    没有语法上歧义的转义其实就是多此一举,增加数据交互的冗余工作。
    楼主的这个 json 格式,如果场景是 Foo = {\"身份\":\"学生\",\"姓名\":\"张三\"},这时的转义其实是多余的。
    而假设是 Foo = {"data": "{\"身份\":\"学生\",\"姓名\":\"张三\"}"},转义是需要的。
    ipwx
    ipwx
    Jun 13, 2020
    33
    @maobukui 。。。。 你们是认真的?谁在和你们说写代码的事情?

    假设有个 JSON 存在文本文件里面,文件内容是:

    {\"身份\":\"学生\",\"姓名\":\"张三\"}

    这就根本不符合 JSON 标准啊。你读出来用啥库解析?怕不是当做 JS 执行一遍才行?
    lagoon
    lagoon
    OP
    Jun 13, 2020
    34
    @FutherAll 其实,我估计实际是\\\,所以最终还是保留了\
    lagoon
    lagoon
    OP
    Jun 13, 2020
    35
    @ipwx 但他们确认,这就是符合 json 规范的。。。吵翻了
    lagoon
    lagoon
    OP
    Jun 13, 2020
    36
    @ipwx 不,他们觉得转义合情合理。
    争论,他们的办法是:
    一,直接字符串,var = {\"身份\":\"学生\",\"姓名\":\"张三\"}; 这样实际字符串就没有\了。 可以转。
    二、经过几道转换,然后把\转没了,然后再转 json 。论证没问题。
    ipwx
    ipwx
    Jun 13, 2020
    37
    @lagoon 对啊,评论区就有这种奇葩评论。我也是醉了。
    lagoon
    lagoon
    OP
    Jun 13, 2020
    38
    @Trim21 先把其他的转了,然后再把这个处理一下,再转。

    没办法。。。。
    ralu
    ralu
    Jun 13, 2020❤️1
    39
    https://gist.github.com/Muscipular/24674f3f05b6729bb66470528387ad58
    @lagoon
    压根没毛病
    json 原文

    {
    "code": 200,
    "data": {
    "specs": "[{\"name\":\"容量\",\"values\":[\"120G\",\"260G\"]},{\"name\":\"网络型号\",\"values\":[\"移动\",\"联通\",\"全网通\"]}]"
    },
    "message": "请求成功"
    }
    ETiV
    ETiV
    Jun 13, 2020
    40
    亲,这边没什么好争议的:是你的小伙伴他们错了。
    watzds
    watzds
    Jun 13, 2020 via Android
    41
    @ipwx 那种 json 里套字符串 json 的,要 parse 两次
    lagoon
    lagoon
    OP
    Jun 13, 2020
    42
    @ralu 👍
    cigarzh
    cigarzh
    Jun 13, 2020
    43
    把 https://www.json.org/ 在 A4 纸上打印出来然后狠狠的甩在他脸上
    fundon
    fundon
    Jun 13, 2020
    44
    很明显后端序列化了两次后输出,不是拿一个对象(字典、Map )去序列化,而是拿字符串去序列号
    ipwx
    ipwx
    Jun 13, 2020
    45
    @watzds 那你为啥要这么干?而且套了一个字符串,读出来的值不是带斜杠的啊。。。楼主当然指的是值就有斜杆。
    watzds
    watzds
    Jun 13, 2020 via Android
    46
    @ipwx 我可没这么干。
    见识太少了,前后端都懂的人,对这些不会有困惑。字符串里有引号,当然会转义。

    一种情况是,后端拿到的时候就已经是 json 了,后端也不关心这个 json 的内部(可能是前端生成的配置),直接当一个对象的 string 属性,再把这个对象序列化后传给前端,没记错的话,记得奇妙清单就是这么干的
    iceheart
    iceheart
    Jun 14, 2020 via Android
    47
    传啥都行,先写进接口文档里再搞。
    有歧义就查文档,文档没写的就补上。
    namelosw
    namelosw
    Jun 14, 2020 via iPhone
    48
    这个是合法的 JSON.
    但是这个 JSON 的类型是字符串.
    这个字符串还是个 JSON.
    这个字符串 JSON 解析完是个对象.

    我理解这个接口是想返回这个对象,那应该返回不带转义的,不然就是序列化了两次.
    lagoon
    lagoon
    OP
    Jun 14, 2020
    49
    @namelosw 应该是序列化了 2 次。
    如果只是一次,那么这个\就不会存在了。也不存在混合双打的情况。
    keenkiller
    keenkiller
    Jun 14, 2020
    50
    这一般不是序列化了两次,而是把数据库里的 Json 字段当纯文本返回给客户端了。

    正确的处理方法:在返回之前反序列化一次就可以了。Java+Mybatis 用 TypeHandler 转成 JsonNode 就行,Go 自己写一个类,其他的也类似。
    lagoon
    lagoon
    OP
    Jun 14, 2020
    51
    @tairan2006 是的,其实处理都简单。

    争论的关键点在于这个是不是符合 json 规范的。特别是混合双打的情况下。
    iEverX
    iEverX
    Jun 14, 2020 via Android
    52
    找 json 的规范甩给他
    netnr
    netnr
    Jun 14, 2020
    53
    在获取 JSON 对象时,一个是 字符串,一个是 object
    后端应该处理成 object,不然前端 JSON.parse 解析几次
    返回转义的 JSON 字符串是没问题,但肯定是不推荐的,你看各大服务商提供的接口,不管层级多深,肯定不会有转义字符
    Vitta
    Vitta
    Jun 14, 2020
    54
    记得看过一个大哥发过他们的后端返回过 丨 这个字
    Hieast
    Hieast
    Jun 14, 2020
    55
    这个返回值既不是字符串,也不是对象
    https://www.json.org/json-zh.html
    字符串应该以 `"` 开头,这个返回值不是,所以不是字符串
    对象以 `{` 开头,然后里面的 key 和 value 需要是字符串类型以 `"` 开头,但是里面的 key 和 value 都是以 `\` 开头的,所以也不是对象

    后端返回的是代码原文,得执行 eval 才能正确解析,这个风险肯定很高。这个返回值肯定不是用 json dump 的标准库处理得到的,太奇葩了
    Reficul
    Reficul
    Jun 14, 2020
    56
    V2EX 竟然也能有这么多搞不清序列化的老哥
    rokeyzhao
    rokeyzhao
    Jun 17, 2020
    57
    json 和 json 字符串的区别
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   665 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 75ms · UTC 23:08 · PVG 07:08 · LAX 15:08 · JFK 18:08
    ♥ Do have faith in what you're doing.