我正在为我的webapp设计一个API。
我在考虑只支持JSON响应(不是XML),因为它更精简。
但我刚刚提到这个XML:
<folders>
<folder id="123" private="0" archived="0" order="1">Shopping</folder>
</folders>
我想知道相应的JSON是怎样的。我觉得,在这种情况下,XML会更紧凑。
谢谢, 丹
答案 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"]}}
}
]}
此转换的规则是明确的:
为了安全的空间,有一种方法可以毫不含糊地简化上面提到的映射:
{"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
}
}
}
答案 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将始终更紧凑,因为没有结束标记;)