JSON对应一个带属性的XML?

时间:2010-10-29 22:40:30

标签: xml json

我正在为我的webapp设计一个API。

我在考虑只支持JSON响应(不是XML),因为它更精简。

但我刚刚提到这个XML:

<folders>
    <folder id="123" private="0" archived="0" order="1">Shopping</folder>
</folders>

我想知道相应的JSON是怎样的。我觉得,在这种情况下,XML会更紧凑。

谢谢, 丹

14 个答案:

答案 0 :(得分:18)

也许:

{
  "folders": [
    { "id":123, "private":0, "archived":0, "order":1, "title":"Shopping" },
    ...
  ]
}

因为 XML和JSON之间存在完全对应关系,所以您可以自由(例如必须定义)两个数据结构如何映射。例如,在上面,“folder”元素隐含在“folders”数组中的嵌套对象中。

这可以扩展为:

"folders": [{"folder": { .... }]

等等,但仍然存在无法像XML一样捕获内容+属性的问题。在任何情况下,您的数据结构 - &gt; JSON | XML序列化程序可能以特定方式工作(请请使用库,而不是“手动”JSON-string-munging )。那是; XML和JSON的格式应该由数据结构统一指定(以某种方式)进行传输。

答案 1 :(得分:15)

这种方法支持对XML的逆转换:

{
    "folders": {
        "folder":{ 
        "@": {
            "id": "123",
            "private": "0",
            "archived": "0",
            "order": "1"
            },
        "#": "Shopping"
        }
    }
}

它适用于 js2xmlparser

答案 2 :(得分:7)

YQL如何呈现XML和相应的JSON的示例。无需了解有关YQL的任何信息,但如果您有兴趣,可以查看YQL控制台并在YQL console

中自行试用。

<强> XML

<results>
    <a href="/">NBA</a>
    <a class="topnav" href="#">TEAMS</a>
    <a href="/teams/">Teams</a>
    <a href="/hawks/">Atlanta</a>

<强> JSON

"results": {
  "a": [
    {
     "href": "/",
     "content": "NBA"
    },
    {
     "class": "topnav",
     "href": "#",
     "content": "TEAMS"
    },
    {
     "href": "/teams/",
     "content": "Teams"
    },
    {
     "href": "/hawks/",
     "content": "Atlanta"
    },

答案 3 :(得分:7)

当XML DOM表示为JSON DOM时,有一种名为 badgerfish 的JSON符号/约定尝试标准化(至少它自己的术语)保留大多数低级XML语义的方式(带有当然属性)(见http://badgerfish.ning.com/)。

因此,您可以轻松地将 badgerfishied-json 表示形式转换回XML表示形式,您仍然可以使用您喜欢的XML工具集(对我来说是XPATH / QUERY表达式和工具)来处理结构。 / p>

它也很容易记住语法规则(共9个),如:“属性进入名称以@”开头的属性。您可以在文本编辑器中处理 badgerfishied-json ,而不会不必要地重载您的神经电路。通常你可以在第一遍中记住它们。

答案 4 :(得分:4)

也可以在JSON中压缩,属性与标记

中的值相同

从这里开始:

http://www.json.org/example.html

{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    }
}}  

表示为XML的相同文本:

<widget>
    <debug>on</debug>
    <window title="Sample Konfabulator Widget">
        <name>main_window</name>
        <width>500</width>
        <height>500</height>
    </window>
    <image src="Images/Sun.png" name="sun1">
        <hOffset>250</hOffset>
        <vOffset>250</vOffset>
        <alignment>center</alignment>
    </image>
</widget>

答案 5 :(得分:4)

在我看来,XML和JSON之间最精确的对应关系需要将XML节点表示为三元组(即数组):[name,attributes,value],其名称为字符串,属性为具有属性的对象将键和属性值命名为(字符串)值,并为字符串(对于原子值)或这些三元组的数组赋值。

通过这种映射,JSON等效于

<folders>
    <folder id="123" private="0" archived="0" order="1">Shopping</folder>
</folders>

将是

[  "folders",
   {}, 
   [
      [  "folder", 
         {   "id": "123",
             "private": "0",
             "archived": "0",
             "order": "1"
         },
         "Shopping"
      ]
   ]
]

实际上,这种映射背后的想法是:

1)XML-JSON转换是可逆的。 2)保留子节点的“兄弟”关系

同时,属性节点和值节点之间的区别在这里是明确的。

有意义吗?它是否证明了复杂性开销的合理性?

答案 6 :(得分:1)

修改

http://www.jsonml.org/提倡采用类似的方法。他们创造了json标记语这一术语。

您可以选择任何您喜欢的地图,但如果您映射

<el attr="value">
  txt
</el>

{"el":{"attr":"value","content":"txt"}}
那么你将如何映射:

<el attr="value" content="txt1">txt2</el>

我利用了禁止使用某些属性的事实。

{"el":{"attr":"value", "content":"txt1", "":["txt"]}

或者更复杂的例子:

<widget>
  <debug>on</debug>
  <window title="Sample Konfabulator Widget">
    I just put some text here
    <name>main_window</name>
    <width>500</width>
    <height>500</height>
  </window>
  <image src="Images/Sun.png" name="sun1">
    <hOffset>250<unit>mm</unit></hOffset>
    <vOffset>250</vOffset>
    <alignment>center</alignment>
  </image>
</widget>

可以映射到:

{"widget":{"":[
  {"debug":{"":["on"]}},
  {"window":{"title":"Sample Konfabulator Widget", "": [
    "I just put some text here",
    {"name":{"":["main window"]}},
    {"width":{"":["500"]}},
    {"height":{"":["500"]}}
  ]},
  {"image":{"src":"Images/Sun.png", "name":"sun1", "":[
    {"hOffset":{"":["250",{"unit":{"":["mm"]}}]}},
    {"vOffset":{"":["250"]}},
    {"alignment":{"":["center"]}}
  }
]}

此转换的规则是明确的:

  • 将元素转换为对象。
  • 对象键是元素名称。
  • 对象值是一个对象本身,具有:
    • attibute映射到对象属性。 (键/值)
    • 对象内容映射到特殊属性。
      • 特殊属性名称是空字符串。这永远不会与xml attribyte名称冲突。
      • 特殊属性值是一个数组。
      • 在数组中,纯文本表示为字符串。
      • 在数组中,元素表示为对象,如上所述。

为了安全的空间,有一种方法可以毫不含糊地简化上面提到的映射:

{"widget":{"":[
  {"debug":"on"},
  {"window":{"title":"Sample Konfabulator Widget", "": [
    "I just put some text here",
    {"name":"main window"},
    {"width":"500"},
    {"height":"500"}
  ]},
  {"image":{"src":"Images/Sun.png", "name":"sun1", "":[
    {"hOffset":["250",{"unit":"mm"}]},
    {"vOffset":"250"},
    {"alignment":"center"}
  }
]}
  • 如果元素没有任何属性,则值对象(包含映射到数组的特殊空字符串)将直接替换为数组。所以而不是:

    {&#34; hOffset&#34; {&#34;&#34;:[&#34; 250&#34; {&#34;单元&#34; {&#34;&# 34;:[&#34;毫米&#34;]}}]}}

你得到了

{"hOffset":["250",{"unit":["mm"]}]}
  • 如果元素内容只是文本,则包含字符串值的数组将直接替换为字符串值,因此您得到:

    {&#34; hOffset&#34;:[&#34; 250&#34; {&#34;单元&#34;:&#34;毫米&#34;}]}

这样,总会有一种方法将jml(json标记语言)映射回xml(或html)

答案 7 :(得分:0)

JSON比XML更统一,不区分纯文本属性和分层内容。您的示例的自然表示将是

[
  {"id": 123, "private": 0, "archived": 0, "order": 1, "name": "Shopping"}
]

这比相应的XML更紧凑。

答案 8 :(得分:0)

“content”用于实际文本,而属性是结果JSON中的兄弟:

{ "folders":
 { "folder":
  {
   "archived":0,
   "private":0,
   "id":123,
   "content":"Shopping",
   "order":1
  }
 }
}

Java implementation details

答案 9 :(得分:0)

我遇到了一个场景,它需要XML和JSON来根据传入的内容输入和输出。我找到了一种适用于XML Attributes / Properties和JSON的方法。现在注意,它是用Java编码的,它以这种方式工作。

我的XML示例:

<Log>
    <datetime>05/05/2017 13:45:22</datetime>
    <sessionid>2da236d2-3852-4a09-8067-198193d2828b</sessionid>
    <message msgType="Debug">This is my message</message>
</Log>

我的JSON示例:

{
    "datetime":"05/05/2017 13:45:22",
    "sessionid":"2da236d2-3852-4a09-8067-198193d2828b",
    "message": {
        "content":"This is a testa",
        "msgType":"Debug"
    }
}

我是如何通过代码 Log.java

使其工作的
package log;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "Log")
public class Log {
    @JacksonXmlProperty(localName = "datetime")
    private String datetime;
    @JacksonXmlProperty(localName = "sessionid")
    private String sessionid;
    @JacksonXmlProperty(localName = "message")
    private Message message;

    public Log() {
        this.sessionid = "0";
        this.datetime = "";
        this.message = new Message();
    }

    public String getDatetime() {
        return datetime;
    }

    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }

    public String getSessionid() {
        return sessionid;
    }

    public void setSessionid(String sessionid) {
        this.sessionid = sessionid;
    }

    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }
}

Message.java ,请注意下面的@JacksonXmlText,这是关键:

package log;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;

public class Message {
    @JacksonXmlProperty(localName = "msgType", isAttribute = true)
    private String msgType;
    @JacksonXmlText
    private String content;

    public Message() {
        this.content = "";
    }

    public String getMsgType() {
        return msgType;
    }

    public void setMsgType(String msgType) {
        switch(msgType.toLowerCase())
        {
        case "test":
        case "debug":
        case "warn":
        case "error":
            break;
        default:
            msgType = "Unknown";
            break;
        }

        this.msgType = msgType;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

LogController.java 中的来电者:

..
@RequestMapping(value = "/Logger", produces={"application/xml", "application/json"}, consumes={"application/xml", "application/json"})
public ResponseEntity<String> Logger(@RequestBody String logInfo, @RequestHeader("Content-Type") String contentType) {
    try 
    {
        String xml = "";
        Log logObj = null; 
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("Content-Type", contentType);

        if (contentType.toLowerCase().contains("json"))
        {
           ObjectMapper mapper = new ObjectMapper();
           logObj = mapper.readValue(logInfo, Log.class);
           xml = mapper.writeValueAsString(logObj);
        }
        else if (contentType.toLowerCase().contains("xml"))
        {
           XmlMapper xmlMapper = new XmlMapper();
           logObj = xmlMapper.readValue(logInfo, Log.class);
           xml = xmlMapper.writeValueAsString(logObj);
        }
        else
           return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);

        //TODO GWL
        //Save Log data, via Async Web Service, Data, or System 
        return new ResponseEntity<String>(xml, responseHeaders, HttpStatus.OK);
    } 
    catch( Exception ex)
    {
        ex.printStackTrace();
        return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
    }
}

答案 10 :(得分:0)

如果您想概述XML到JSON转换的各种约定,可以在以下位置概述:http://wiki.open311.org/JSON_and_XML_Conversion/

一个支持多个约定的python库是xmljson(https://github.com/sanand0/xmljson)。

答案 11 :(得分:0)

开场警告:在这个答案中,我故意放弃了原始问题,并在一定程度上扩大了范围。有时要问一个问题背后的问题,我们需要首先看一下全局。

就像所有动物一样,从JSON到XML的所有转换以及从XML到JSON的所有转换都是不相等的。这个问题不可能有数学上正确的答案,即使答案正确,也可能是错误的。所有答案都将视情况而定,并取决于确切的用例。

JSON和XML都支持和省略使完善,可逆和本地翻译变得困难的概念。

仅举几例:

  • XML需要一个根元素。 JSON不会。

  • XML区分元素和属性。属性是叶子,元素可能是叶子或分支。 JSON对象与Elements接近,但是没有与Attributes直接等效的对象。

  • JSON具有数组;最接近的XML等效项是父元素,但是在只有一个子元素的情况下,某些翻译会出错。

  • XML具有名称空间…..对这些名称的评论越少越好……

  • JSON旨在精简,轻巧,并且比XML更接近YAML(以我的拙见)。

在源语言中存在概念但在目标语言中不存在的情况下,我们需要在翻译中发挥创造力和创造力。您的用例是关键。

例如

  • 结果应该在目标语言中尽可能地原生吗?我们可以在JSON中这样建模吗?我们会用XML这样建模吗?

  • 即使以牺牲“原始感觉”为代价,结果是否也可以还原为原始来源?

  • 紧凑性是一个标准吗?对于使用重于元素的XML的JSON可能是这种情况,但对于从XML转换并设计为反向翻译的JSON可能不是这种情况。

与人类语言进行比较:在瑞士德语中,我们喜欢我们的小名词:名词通常被简化为小形式,在英语中这会很奇怪;但更奇怪的是,我们有动词的缩影!

因此:“ wir machen esköchele”在技术上可能会翻译为“我们会少量做饭”或“我们会做一点饭”,但要么用英语讲得不好和不正确,要么就以某种方式错过了这个主意。

“我们将做点烹饪”或“我们将做一些有趣的烹饪”将更接近最初的想法。但是我怀疑Anthea Bell(来自Asterix到英国的翻译名声)确实可以理解这一点。 “让我们做一场盛宴……。”

回到原始问题。 Python程序员有pythonesque的概念:=最适合python的核心精神。 user166390的答案(在此答案时已被接受的答案)让我印象最深刻。

答案 12 :(得分:0)

我对XML表示的选择如下,以确保它可以某种方式可逆,(使用您的示例):

    <folders>
        <folder id="123" private="0" archived="0" order="1">Shopping</folder>
    </folders>

翻译为:

    {
      "folders": [
        {
          "folder": [
            {
              "@id": 123,
              "@private": 0,
              "@archived": 0,
              "@order": 1,
              "$t": "Shopping"
            }
          ]
        }
      ]
    }

因此,通过使用@作为“属性”的指示符和$t作为“文本内容”的指示符,我可以将JSON字符串还原为原始XML的真实版本。

XML2JSON是执行此转换的一个不错的Node程序包,尽管它对属性没有任何特殊要求,并且需要一些额外的代码才能产生此输出。

答案 13 :(得分:-2)

排除长度始终相同的属性名称,JSON将始终更紧凑,因为没有结束标记;)