如何在JSON中表达XML标记属性?

如何在JSON中表达XML标记属性?,xml,json,Xml,Json,我正在为我的webapp设计一个API 我想只支持JSON响应(而不是XML),因为它更精简 但我刚刚谈到了这个XML: <folders> <folder id="123" private="0" archived="0" order="1">Shopping</folder> </folders> 购物 我想知道对应的JSON会是什么样子。我觉得,在这

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

我想只支持JSON响应(而不是XML),因为它更精简

但我刚刚谈到了这个XML:

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

购物

我想知道对应的JSON会是什么样子。我觉得,在这种情况下,XML会更加紧凑。

在JSON中也可以紧凑,属性与标记中的值完全相同

从这里开始:


以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>

在…上
主窗口
500
500
250
250
居中

不包括总是相同长度的属性名,JSON将总是更紧凑,因为它没有结束标记;)

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

[
  {"id": 123, "private": 0, "archived": 0, "order": 1, "name": "Shopping"}
]
这仍然比相应的XML更紧凑。

也许:

{
  "folders": [
    { "id":123, "private":0, "archived":0, "order":1, "title":"Shopping" },
    ...
  ]
}
因为XML和JSON之间没有精确的对应关系,所以您可以自由(例如,必须定义)这两种数据结构的映射方式。例如,在上面的例子中,“folder”元素隐含在“folders”数组中的嵌套对象中

这可以扩展为:

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

等等,但仍然存在一个问题,即不能像XML那样一致地捕获内容+属性。在任何情况下,您的数据结构->JSON | XML序列化程序都可能以特定的方式工作(请,请使用库,而不是“手动滚动”JSON字符串)。就是,;XML和JSON的格式应该(以某种方式)由用于传输的数据结构统一规定。

YQL如何表示XML和相应JSON的示例。不需要了解任何关于YQL的知识就可以理解这一点,但是如果您感兴趣,您可以查看YQL控制台并在

XML

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

有一种称为badgerfish的JSON表示法/约定试图标准化(至少是它自己的术语)在XML DOM表示为JSON DOM(当然带有属性)时保留大多数低级XML语义的方式(请参阅)

因此,您可以轻松地将BadgerFished json表示转换回XML表示,并且仍然可以使用您最喜欢的XML工具集(对我来说,它的XPATH/查询表达式和工具)处理该结构


它还可以很容易地记住语法规则(共9条),比如:“属性放在名称以@开头的属性中”。您可以在文本编辑器中处理BadgerFished json,而不会不必要地使神经回路过载。通常,您可以在第一遍就记住它们。

在我看来,XML和JSON之间最精确的对应关系需要将XML节点表示为三元组(即数组):[name,attributes,value],name为字符串,attributes为对象,attribute name为键,attribute value为(string)值,和值一个字符串(用于原子值)或这样的三元组数组

通过这种映射,JSON等价于

<folders>
    <folder id="123" private="0" archived="0" order="1">Shopping</folder>
</folders>
实际上,这种映射背后的思想是:

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

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


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

此方法支持到XML的反向转换:

{
    "folders": {
        "folder":{ 
        "@": {
            "id": "123",
            "private": "0",
            "archived": "0",
            "order": "1"
            },
        "#": "Shopping"
        }
    }
}
它可以与js2xmlparser一起正常工作。

实际文本使用“内容”,而属性是其在结果JSON中的同级:

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

我遇到了一个场景,根据传入的内容,输入和输出都需要XML和JSON。我找到了一种处理XML属性和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>
如何通过代码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;
    }
}
..
@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);
    }
}
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中的调用者:

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;
    }
}
..
@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);
    }
}
。。
@RequestMapping(value=“/Logger”,products={“application/xml”,“application/json”},consumes={“application/xml”,“application/json”})
公共响应属性记录器(@RequestBody String logInfo、@RequestHeader(“内容类型”)String contentType){
尝试
{
字符串xml=”“;
logObj=null;
HttpHeaders responseHeaders=新的HttpHeaders();
添加(“内容类型”,contentType);
if(contentType.toLowerCase()包含(“json”))
{
ObjectMapper mapper=新的ObjectMapper();
logObj=mapper.readValue(logInfo,Log.class);
xml=mapper.writeValueAsString(logObj);
}
else if(contentType.toLowerCase()包含(“xml”))
{
XmlMapper XmlMapper=新的XmlMapper();
logObj=xmlMapper.readValue(logInfo,Log.class);
xml=xmlMapper.writeValueAsString(logObj);
}
其他的
返回新的响应属性(HttpStatus.BAD_请求);
//TODO GWL
//通过异步Web服务、数据或系统保存日志数据
返回新的ResponseEntity(xml、responseHeaders、HttpStatus.OK);
} 
捕获(例外情况除外)
{
例如printStackTrace();
返回新的响应属性(HttpStatus.BAD_请求);
}
}
编辑

一个类似的方法也被提倡。他们创造了术语json标记语言


你可以选择任何你喜欢的贴图,但是如果你

<el attr="value">
  txt
</el>
那么您将如何映射:

<el attr="value" content="txt1">txt2</el>
或者更复杂的例子:

<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>
此转换的规则是明确的:

  • 元素转换为对象
  • 对象键是元素名
  • 对象值是对象本身,具有:
    • attibute映射到对象属性。(键/值)
    • 目标
      {"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"]}}
        }
      ]}
      
      {"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"}
        }
      ]}
      
      {"hOffset":["250",{"unit":["mm"]}]}