如何在JSON中表达XML标记属性?
我正在为我的webapp设计一个API 我想只支持JSON响应(而不是XML),因为它更精简 但我刚刚谈到了这个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会是什么样子。我觉得,在这
<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"]}]}