【问题标题】:JSON - is there any XML CDATA equivalent?JSON - 是否有任何等效的 XML CDATA?
【发布时间】:2013-02-02 20:35:24
【问题描述】:

我正在寻找一种 json 解析将按原样获取信息的方式(就好像它是 CDATA)——而不是尝试序列化它。 我们同时使用 .net 和 java(客户端和服务器)——所以答案应该是关于 JSON 结构 有没有办法实现这种结构?

谢谢。

【问题讨论】:

    标签: java json .net-4.0 cdata


    【解决方案1】:

    http://www.json.org/ 详细描述了 JSON 格式。根据它,JSON 不支持“类似于 CDATA”的值类型。

    要实现 CDATA 结构,您可以应用自定义逻辑来处理基于字符串的值(并且对于 .net 和 java 实现都采用相同的方式)。例如

    { 
      "type" : "CDATA",
      "value" : "Value that I will handle with my custom logic on java and .net side"
    }
    

    【讨论】:

    • 这当然会失败,因为“值”不能包含文字数据而不转义某些字符。
    • 重点是能够放入像value is with double quotes like " and : an more "这样的原始字符串值
    【解决方案2】:

    JSON 中没有等效的 XML CDATA。但是您可以使用 base64 之类的方法将消息编码为字符串文字。详情请见this question

    【讨论】:

    • 将二进制数据放入 JSON 似乎最好/最容易通过 Base64 编码完成。参考:stackoverflow.com/questions/1443158.
    • 尽管它可能是最好的解决方案,但它仍然是一个糟糕的主意。 JSON 应该是人类可读和机器可读的(就像 xml 一样),而编码打破了这种模式。此外,字符串会变得非常大。
    【解决方案3】:

    这是上述拉曼建议的发展。

    我喜欢 JSON 格式,但有两件事我想用它做而不能做:

    1. 使用文本编辑器将一些任意文本粘贴到值中
    2. 如果 XML 包含 CDATA 部分,则在 XML 和 JSON 之间进行透明转换。

    此线程与这两个问题密切相关。

    我建议通过以下方式克服这个问题,这不会破坏 JSON 的正式定义,我想知道如果我这样做是否会存储任何问题?

    1. 定义一个与 JSON 兼容的字符串格式如下:

      "<![CDATA[ (some text, escaped according to JSON rules) ]]>"

    2. 用我最喜欢的编程语言编写一个 Unescape 例程,它可以对 <![CDATA[ and ]]> 之间的任何内容进行转义。这将在向我的文本编辑器提供任何 JSON 文件之前调用。

    3. 编写补充例程以在编辑文件后调用,该例程根据 JSON 规则重新转义 <![CDATA[ and ]]> 之间的任何内容。

    然后,为了将任意数据粘贴到文件中,我需要做的就是通过在 JSON 字符串后键入 <![CDATA[ before and ]]> 来指示任意数据的开始和结束。

    这是在 Python3 中在文本编辑之前和之后调用的例程: lang-python3

    escape_list = {
        8 : 'b',
        9 : 't',
        10: 'n',
        12: 'f',
        13: 'r',
        34: '"',
    }   #List of ASCII character codes to escape, with their escaped equivalents
    
    escape_char = "\\"  #this must be dealt with separately
    unlikely_string = "ZzFfGgQqWw"
    
    shebang = "#!/json/unesc\n"
    start_cdata = "<![CDATA["
    end_cdata = "]]>"
    
    def escapejson(json_path):
    
        if (os.path.isfile(json_path)): #If it doesn't exist, we can't update it
            with open(json_path) as json_in:
                data_in = json_in.read()   #use read() 'cos we're goint to treat as txt
            #Set direction of escaping
            if (data_in[:len(shebang)] == shebang):   #data is unescaped, so re-escape
                data_in = data_in[len(shebang):] 
                unescape = False
                data_out = ""
            else:
                data_out = shebang
                unescape = True 
    
            while (data_in != ""):  #while there is still some input to deal with
                x = data_in.find(start_cdata)
                x1 = data_in.find(end_cdata)
                if (x > -1):    #something needs escaping
                    if (x1 <0):
                        print ("Unterminated CDATA section!")
                        exit()
                    elif (x1 < x):  #end before next start
                        print ("Extra CDATA terminator!")
                        exit()
                    data_out += data_in[:x]
                    data_in = data_in[x:]
                    y = data_in.find(end_cdata) + len(end_cdata)
                    to_fix = data_in[:y]    #this is what we're going to (un)escape
                    if (to_fix[len(start_cdata):].find(start_cdata) >= 0):
                        print ("Nested CDATA sections not supported!")
                        exit()
                    data_in = data_in[y:]   #chop data to fix from front of source
                    if (unescape):
                        to_fix = to_fix.replace(escape_char + escape_char,unlikely_string)
                        for each_ascii in escape_list:
                            to_fix = to_fix.replace(escape_char + escape_list[each_ascii],chr(each_ascii))
                        to_fix = to_fix.replace(unlikely_string,escape_char)
                    else:
                        to_fix = to_fix.replace(escape_char,escape_char + escape_char)
                        for each_ascii in escape_list:
                            to_fix = to_fix.replace(chr(each_ascii),escape_char + escape_list[each_ascii],)
                    data_out += to_fix
                else:
                    if (x1 > 0):
                        print ("Termination without start!")
                        exit()
                    data_out += data_in
                    data_in = ""
    
            #Save all to file of same name in same location
            try:
                with open(json_path, 'w') as outfile:
                    outfile.write(data_out)
            except IOError as e:
                print("Writing "+ json_path + " failed "+ str(e))
        else:
            print("JSON file not found")
    

    对以下合法 JSON 数据进行操作

    {
        "test": "<![CDATA[\n We can put all sorts of wicked things like\n \\slashes and\n \ttabs and \n \"double-quotes\"in here!]]>"
    }
    

    ...将产生以下内容:

    #!/json/unesc
    {
        "test": "<![CDATA[
     We can put all sorts of wicked things like
     \slashes and
        tabs and 
     "double-quotes"in here!]]>"
    }
    

    在此表单中,您可以在标记之间粘贴任何文本。再次调用例程会将其改回原来的合法 JSON。

    我认为这也可以在使用 CDATA 区域转换为 XML 或从 XML 转换时起作用。 (接下来我要试试!)

    【讨论】:

    • 不幸的是,StackOverflow 的编辑器删除了我的 CDATA 字符串,所以它没有意义。还是一样,加了几个空格:
    • stackoverflow.com/editing-help我错过了什么吗?
    • 一点也不,云诺施!你和我都在做同样的事情! :-) 谢谢你的帮助。
    • 我在上面的代码中发现了一个小错误: if(unescape): .... else: 应该是: ` to_fix = to_fix.replace(escape_char + escape_char,unlikely_string) #doublequotes to notished string对于escape_list 中的each_ascii: to_fix = to_fix.replace(escape_char + escape_list[each_ascii],chr(each_ascii)) to_fix = to_fix.replace(unlikely_string,escape_char)` ... 其中不太可能出现的长字符串值数据
    • 克里斯,你应该真正接受editing 你的帖子而不是评论它们的想法。
    【解决方案4】:

    您可以创建 YAML 文件并转换为 JSON。例如:

    test.yaml

    storage:
      files:
      - filesystem: root
        path: /etc/sysconfig/network/ifcfg-eth0
        mode: 644
        overwrite: true
        contents:
          source: |
            data:,
            IPV6INIT=yes
            IPV6_AUTOCONF=yes
    

    ...然后运行yaml2json_pretty(稍后显示),如下所示:

    #!/bin/bash
    
    cat test.yaml | yaml2json_pretty > test.json
    

    ... 产生:

    test.json

    {
      "storage": {
        "files": [
          {
            "filesystem": "root",
            "path": "/etc/sysconfig/network/ifcfg-eth0",
            "mode": 644,
            "overwrite": true,
            "contents": {
              "source": "data:,\nIPV6INIT=yes\nIPV6_AUTOCONF=yes\n"
            }
          }
        ]
      }
    }
    

    这是yaml2json_pretty的源码:

    #!/usr/bin/env python3
    
    import sys, yaml, json
    print(json.dumps(yaml.load(sys.stdin.read(),Loader=yaml.FullLoader), sort_keys=False, indent=2))
    

    更多类似yaml2json_pretty的技巧在:http://github.com/frgomes/bash-scripts

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 2015-12-06
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-30
      相关资源
      最近更新 更多