深入了解 JSON 与 XML,第 3 部分:XML 和 JSON 的未来
已发表: 2022-03-11在本文的第 2 部分中,我们仔细研究了 JSON 作为数据交换,并评估了它在简单应用程序和复杂应用程序中的优势和劣势。 JSON 是最简洁、最紧凑的人类可读格式,但其基本简单性在用于复杂用例时可能会导致意想不到的影响。 使用 JSON 作为数据交换,开发人员只能自己实现 JSON 本身缺少的功能,从而产生试图弥补差距的耦合和非标准解决方案。 对于坚持断言无错误操作的企业解决方案,使用 JSON 可能会导致不希望的模式,从而影响系统的代码质量、稳定性和对未来未知数的弹性。 XML 是否提供了帮助应用程序降低这种风险的功能? 可以用 JSON 实现相同的功能吗? 仔细研究 XML 作为数据交换将揭示其在降低软件风险方面的优势,并让开发人员更好地理解有助于提高其应用程序质量的模式。
在本文的第 3 部分中,我们将:
- 探索 XML 作为数据交换并评估其在支持复杂需求方面的优势。
- 讨论 JSON 的未来并探索将 XML 的优势带入 JSON 的解决方案,以使开发人员能够构建更稳定、更能抵抗错误和未来未知的软件。
XML 很容易被标记为 JSON 的复杂和冗长的替代方案。 w3schools.com 网站(一个流行的 Web 标准参考资料)仅提供了 58 个单词,主题为“为什么 JSON 比 XML 更好” 1 。 对 JSON 与 XML 的这种简单评估具有误导性,因为 XML 提供的不仅仅是数据交换。 事实上,XML不仅仅是为数据交换而设计的,而是作为为任何应用程序指定自定义标记语言的语言。 凭借其严格的语义,XML 定义了一个标准来断言任何 XML 子语言的 XML 文档的数据完整性。 许多开发人员认为“XML 失败并被 JSON 取代”,但事实并非如此。 最初,XML 被设想用于解决所有数据互操作性问题,直到今天仍然是“世界上使用最广泛的表示和交换信息的格式”。 2
JSON 很简单,而 XML 很强大
在本文的第 2 部分中,我们探讨了涉及消费者驱动合同 (CDC)、协议演进和消息验证的数据交换。 使用 JSON 作为数据交换,我们的示例 - 欧洲银行 - 面临着为与零售商交换数据提供风险缓解解决方案的挑战。 该银行希望软件模式能够实现低耦合、高封装以及对未来未知事物的高弹性。 然而,使用 JSON 作为数据交换,银行呈现出的模式导致了相反的结果:低封装、高耦合以及对未来未知的较低弹性。
让我们重温一下欧洲银行的例子,用 XML 代替 JSON 作为数据交换格式。 以下 XML 消息等效于每种帐户标识符类型的 JSON 消息:SWIFT、IBAN 和 ACH。
<message xsi:type="swift" xmlns="urn:bank:message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <code>CTBAAU2S</code> </message> <message xsi:type="iban" xmlns="urn:bank:message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <code>DE91 1000 0000 0123 4567 89</code> </message> <message xsi:type="ach" xmlns="urn:bank:message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <code>379272957729384</code> <routing>021000021</routing> </message>
尽管原始字节计数效率立即下降,但 XML 通过支持更广泛的数据交换来证明其冗长是合理的。 通过使用 JSON 对数据进行编码,我们能够解决数据交换的直接需求,但无法支持多种消息变体或其验证。 为了解决围绕消费者驱动的合同的范围,开发人员需要实现自定义代码,这将导致消息格式、其内容及其处理的功能实现之间的逻辑耦合。 或者,开发人员可以选择拼凑一组库和框架的拼图,以满足更高的要求。 这两种方法都会在数据交换之上产生一层洋葱层,这些层直接耦合到应用程序。 然而,通过使用 XML 对数据进行编码,我们能够在没有耦合的情况下解决很多需求移动。
XML 消息等价物利用 XML 标准的两个特殊特性:名称空间和实例类型。 xmlns="urn:bank:message"
属性指定消息的命名空间, "xsi:type"
属性指定其实例类型,如"swift"
、 "iban"
或"ach"
。 这两个属性是 XML 标准,允许消息处理器识别消息的类型以及取消引用定义验证规则的模式。
XML 模式代表 JSON 和 XML 之间的关键区别。 使用模式,开发人员可以将消息格式的规范定义封装在与应用程序分离的介质中,并定义值约束以提供由 XML 处理器强制执行的验证规则。 欧洲银行的示例模式(具有namespace: xmlns="urn:bank:message"
),带有类型描述符和值约束,是以下 XML 模式文档 (XSD):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns="urn:bank:message" targetNamespace="urn:bank:message"> <xs:complexType name="format" abstract="true"/> <xs:complexType name="swift"> <xs:complexContent> <xs:extension base="format"> <xs:sequence> <xs:element name="code"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="[AZ]{6}[A-Z0-9]{2}([A-Z0-9]{3})?"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="iban"> <xs:complexContent> <xs:extension base="format"> <xs:sequence> <xs:element name="code"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="[AZ]{2}\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4} ?\d{0,2}"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="ach"> <xs:complexContent> <xs:extension base="format"> <xs:sequence> <xs:element name="code"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="\w{1,17}"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="routing"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="\d{9}"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="message" type="format"/> </xs:schema>
这个 XML 模式在逻辑上等同于第 2 部分中的isValid(message)
函数。乍一看,这个 XML 模式比isValid(message)
详细得多。 然而,两者之间的根本区别在于isValid(message)
与应用程序耦合,而 XML 模式则不是。 XML 模式是一种用于表达关于 XML 文档的约束的语言,并且有几种不同的模式语言被广泛使用,其中主要的有:文档类型定义 (DTD)、Relax-NG、Schematron 和 W3C XML 模式定义 (XSD )。 3对于欧洲银行,XML 模式为更高层的需求提供了一种降低风险的解决方案,而无需耦合。
XML 模式可降低软件风险。 使用 XML,验证消息的规则以一种模式语言表达,这种语言与应用程序脱节,因此不耦合到应用程序。 由于 XML 模式与系统完全分离,因此消息格式的逻辑含义与其处理的功能实现是解耦的。 XML 模式为欧洲银行提供了一个封装层,该层单独负责消息验证、可变性、版本控制等的上下文。
XML 模式代表了消费者驱动合同的规范定义。 对于欧洲银行来说,这提供了一种降低风险的方法来将 $\xi_0$ 减少到接近 0。由于模式与银行和零售商分离,双方都可以使用它来验证和执行合同。
为什么 XML 模式如此冗长?
XML 模式规范为开发人员提供了一种语言来实现用于定义和约束任何 XML 文档的所有组成部分的结构和逻辑模式。 使用 XML 模式,开发人员能够将更深层次的含义嵌入到 XML 文档的每个结构和逻辑部分中。 例如,XML 模式允许:
- 为组成字符串定义正则表达式约束,
- 定义成分编号的范围和格式,
- 定义必需和可选的组成元素和属性,
- 在文档中定义关键和参考要求,等等。
使用 XML 模式,系统可以依靠通用 XML 验证器来断言每个输入消息的有效性,本质上将“错误空间”$\xi_0$ 减少到接近 0,并自动将业务逻辑与错误输入隔离开来。
未来发展的风险
系统可以利用 XML 规范的固有特性来降低未来开发的软件风险。 通过以 XML 模式的形式就规范性合同达成一致,系统定义了所有要交换的对象和属性(对于 XML 的元素和属性)的规则和约束。 此后,系统能够利用更广泛的 XML 规范来解决消息可变性、协议版本控制和内容验证问题。 例如,XML 命名空间为 XML 消息提供以下必要信息:
- 识别消息的版本。
- 取消引用规范合同模式。
- 验证文档的正确性。
借助 XML 模式提供的广泛特性和功能,围绕数据交换的大多数复杂需求都可以通过 XML 本身来解决。 这就是 Charles Goldfarb 博士在说“[XML 是] 计算的圣杯”时所指的。 4
XML 模式可帮助应用程序对错误具有弹性,并能适应未来的变化。
XML 是一种被广泛接受且经过彻底审查的规范,其中包含可用于所有平台的无数库,以帮助处理和验证 XML 文档。 使用 XML 作为数据交换格式,开发人员能够解决直接需求以及与消费者驱动的合同、消息可变性、协议版本控制和内容验证相关的需求。 XML 使开发人员能够对冲复杂需求的风险,更重要的是,未来未知的风险。
XML 不仅仅是数据交换,而且可用于解决比 JSON 更大的问题。 从这个角度来看,XML 的范围覆盖了洋葱的大部分,因此洋葱的几个层包含在 XML 本身的范围内。

在为应用程序选择最佳数据交换格式时,是我们关心的只是洋葱的中心,还是整个洋葱?
JSON 和 XML 之间的根本区别
XML 提供的不仅仅是数据交换,而且可用于解决比 JSON 更大的问题。 围绕数据交换的复杂需求范围由 XML 提供,允许系统利用符合标准的库和框架,与应用程序分离。
XML 是一种通过设计解决复杂需求范围的规范,它是由 W3C 定义并得到所有相关软件供应商和语言平台支持的标准。 通过使用 XML 作为数据交换,应用程序自动从软件风险的系统性降低中获益。
JSON 的未来
不可否认,JSON 将继续存在。 随着 JavaScript 作为当今最广泛使用的开发平台,JSON 已成为最突出的数据交换格式。 对于复杂度较低的小型项目,JSON 非常适合。 但是,随着我们努力为未来创建更大更好的应用程序,我们软件的总体复杂性注定会增加。 以 XML 的强大功能为例,几个小组努力为 JSON 发明类似的标准。
JSON 的根本缺陷在于它缺乏为其文档的逻辑成分的规范性描述提供通用标准。
JSON 模式
2009 年,一个小组启动了 JSON 模式5 ,这是一个用于注释和验证 JSON 文档的词汇表。 JSON 模式使用 JSON 语义为 JSON 文档的组成部分定义一组规则和约束,并且不同平台上的多个项目已经实现了支持 JSON 模式规范的库。 虽然还不是官方标准,但 JSON 模式项目为类似于 XML 模式规范的需求范围提供了解决方案。 使用 JSON 模式词汇,开发人员可以定义 JSON 文档的逻辑和结构规则和约束。 然后,该模式可用于帮助处理和验证带有与应用程序分离的库的 JSON 文档,从而减少在应用程序中混合未封装代码的需要。 使用 JSON 模式,开发人员可以选择 JSON 作为其数据交换的格式,并以降低风险的方式解决以前单独使用 JSON 无法解决的复杂需求。
JSON 模式项目是一项社区努力,经过十年的修订,成为 JSON 模式的主流规范。 虽然它还不是一个标准,但 JSON 模式项目的流行表明了对这种解决方案的兴趣程度。 从概念上讲,JSON 模式规范类似于 XML 模式,但两者的比较揭示了它们的模型、功能和语义之间的差异。 例如,尽管该语言定义了广泛的属性来限制 JSON 值类型的范围,但它的众多属性允许表达自相矛盾的模式定义。
例如,以下摘录定义了一个包含三个属性的"object"
类型: "number"
、 "street_name"
和"street_type"
。
{ "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "type": "string", "enum": ["Street", "Avenue", "Boulevard"] } } }
"object"
类型的定义接受额外的约束,其中之一是"minProperties"
。 通过用"minProperties": "4"
修改上面的"object"
类型定义,定义变得毫无意义,因为只为对象显式定义了三个属性。

JSON 模式具有相当多的约束属性,其中许多对于有效限制 JSON 文档是必不可少的,其中许多是相互重叠的。 由于约束属性在含义上重叠,JSON 模式词汇表提出了两大挑战:
- 由于词汇量广泛以及语义中不寻常或非常规的细微差别,它需要开发人员更高的学习曲线。
- 验证库实现起来更加困难,导致解决方案以不同的方式实现灰色区域,从而导致实现不一致。
XML 模式语言本身并非完全不允许表达自相矛盾的定义,但它们的数量要少得多且受到限制。 事实上,XML 模式规范的开发密切关注开发人员和实现该规范的库的易用性。 此外,JSON 模式项目只定义了模式语言的规范,但存在许多实现该规范的社区项目。
JSON 模式验证器6是一个流行的项目,它为 Java 平台实现了 JSON 模式验证器。 通过将此库集成到 Java 应用程序中,应用程序能够断言所有交换的 JSON 文档的一致性。 JSON 模式规范的其他实现可用于各种平台。
对于欧洲银行,让我们使用 JSON 模式来实现带有帐户标识符的 JSON 消息的模式。
{ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "swift": { "type": "object", "properties": { "type": { "type": "string", "pattern": "swift" }, "code": { "type": "string", "pattern": "(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}" }, "required": ["type", "code"] } }, "iban": { "type": "object", "properties": { "type": { "type": "string", "pattern": "iban" }, "code": { "type": "string", "pattern": "[AZ]{2}\\d{2} ?\\d{4} ?\\d{4} ?\\d{4} ?\\d{4} ?\\d{0,2}" }, "required": ["type", "code"] } }, "ach": { "type": "object", "properties": { "type": { "type": "string", "pattern": "ach" }, "code": { "type": "string", "pattern": "\\w{1,17}" }, "routing": { "type": "string", "pattern": "\\d{9}" }, "required": ["type", "code", "routing"] } } } }
这个 JSON 模式定义了 3 种对象类型: "swift"
、 "iban"
和"ach"
。 它指定正则表达式模式以断言帐户信息不无效,并将"type"
和"code"
声明为每种类型的必需属性,以及"routing"
作为"ach"
类型的必需属性。 使用此 JSON 模式,欧洲银行可以验证其 JSON 输入,以断言消息内容对于每次交互都是正确的。
JSON 模式为 JSON 带来了 XML 的许多功能,但它仍在进行中。 虽然它是一个很好的解决方案,可以用来对冲软件风险,但 JSON 模式规范并不完美。 由于其语言的非正式演变,该语言的演变方向忽略了可以说是重要的特征,并包含令人困惑和非常规的结构和逻辑表达模式。 例如,模式语言缺少定义抽象类型的能力,这可能导致开发人员实施复杂的解决方法,从而导致其自身的相关软件风险。 7
JSON 模式项目为 JSON 模式语言背后的概念带来了宝贵的财富。 尽管其语义的清晰度存在缺陷,但 JSON 模式语言是一种通用的解决方案,它将 XML 的许多功能引入 JSON。
如需详细了解 JSON 模式规范,请参阅了解 JSON 模式。
JSONx
2014 年,另一个小组启动了 JSONx 项目,该项目直接利用 XML 为 JSON 提供同样强大的解决方案。 JSONx 项目是专门为企业创建的,它定义了 JSON 模式定义 (JSD) 语言,该语言与 XML 模式规范非常接近。 JSD 使用 XML 模式作为其模型,定义了与 XML 模式定义语言非常相似的结构和逻辑模式。
对于欧洲银行的示例,让我们使用 JSD 语言为带有帐户标识符的 JSON 消息实现模式。
{ "jx:ns": "http://www.jsonx.org/schema-0.3.jsd", "jx:schemaLocation": "http://www.jsonx.org/schema-0.3.jsd http://www.jsonx.org/schema-0.3.jsd", "message": { "jx:type": "object", "abstract": true }, "swift": { "jx:type": "object", "extends": "message", "properties": { "type": { "jx:type": "string", "pattern": "swift", "nullable": false }, "code": { "jx:type": "string", "pattern": "[AZ]{6}[A-Z0-9]{2}([A-Z0-9]{3})?", "nullable": false, "use": "required" } } }, "iban": { "jx:type": "object", "properties": { "type": { "jx:type": "string", "pattern": "iban", "nullable": false }, "code": { "jx:type": "string", "pattern": "[AZ]{2}\\d{2} ?\\d{4} ?\\d{4} ?\\d{4} ?\\d{4} ?[\\d]{0,2}", "nullable": false } } }, "ach": { "jx:type": "object", "properties": { "type": { "jx:type": "string", "pattern": "ach", "nullable": false }, "code": { "jx:type": "string", "pattern": "\\w{1,17}", "nullable": false }, "routing": { "jx:type": "string", "pattern": "\\d{9}", "nullable": false } } } }
乍一看,JSD 模式在表达上与 JSON 模式相似。 然而,一个区别是 JSD 与 JSON 模式相比的简洁语义。 具体到这个例子,JSD 将"use": "required"
属性放入指定的定义中,而 JSON 模式将此属性与父对象相关联,要求值的名称与属性定义的名称匹配。 约束"use": "required"
仅在"swift"
对象的"code"
属性上指定,其他属性省略,因为"use": "required"
是默认值。 JSD 语言的设计仔细考虑了所有这些细微差别,并为 JSON 模式的表达提供了一种简洁直观的解决方案。
从一开始,JSONx 项目的一个显着特点就是它的主要目的是为开发人员提供清晰和实用的功能。 为了实现这一点,JSD 的一个强大特性是它可以转换为 JSDx——JSD 语言可以用 JSON 文件和 XML 文件表示。 这两种形式都可以一对一翻译,并为开发人员提供了使用高级 XML 编辑工具来帮助创建 JSD 文档以进行实时验证和无错误的能力。
上面的 JSD 模式可以用以下 JSDx 形式表示:
<schema xmlns="http://www.jsonx.org/schema-0.3.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jsonx.org/schema-0.3.xsd http://www.jsonx.org/schema-0.3.xsd"> <object name="swift"> <property name="code" xsi:type="string" pattern="[AZ]{6}[A-Z0-9]{2}([A-Z0-9]{3})?" nullable="false" use="required"/> </object> <object name="iban"> <property name="code" xsi:type="string" pattern="[AZ]{2}\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4} ?\d{0,2}" nullable="false"/> </object> <object name="ach"> <property name="code" xsi:type="string" pattern="\w{1,17}" nullable="false"/> <property name="routing" xsi:type="string" pattern="\d{9}" nullable="false"/> </object> </schema>
JSD 的 JSDx 形式非常强大,因为它为定义 JSON 模式提供了清晰、自我验证和降低风险的规范。
JSD 语言旨在解决自相矛盾定义的问题,并依赖于标准模式来表达约束。 JSD 类型声明和约束定义与 XML 模式定义 (XSD) 语言的设计非常相似,与 XML 中的等效结构非常相似。 JSD(x) 规范为结构和逻辑约束的定义提供了完整的解决方案,并且是自描述的——提供了以 JSD(x) 语言本身表达的 JSD(x) 语言的规范定义。 如需详细了解 JSD(x) 规范,请参阅 JSON 模式定义语言。
除了 JSD(x) 语言之外,JSONx 项目还提供 JSD(x) 处理器和验证器的参考实现以及 Java 平台的类绑定 API 和代码生成器。 通过绑定 API 和生成器,开发人员可以使用 JSD(x) 模式为所需模式中的对象定义自动生成类,这些类可用于解析和编组符合该模式的 JSON 文档。 生成的类在模式和 Java 平台之间提供强类型绑定,表示模式中指定的使用、约束和关系。 通过对模式的强类型绑定,应用程序进一步降低了与未来可能导致不兼容的修改相关的软件风险。
通过利用 Java 的编译器,强类型绑定可以查明与编译时错误的不兼容性,从而有效地将消息处理相关的错误风险降低到接近于零。 这种工程模式使开发人员能够快速而自信地实施更改并解决不兼容问题,而不必依赖运行时来查找错误或故障案例,尤其是不必依赖用户自己偶然发现错误。 绑定 API 是使用 Java 注释实现的,它允许任何类以一种轻量级的方式绑定到具有强类型的 JSD(x) 模式。 JSONx 的强类型绑定和代码生成功能支持 JSD(x) 规范的全部范围,专为满足企业解决方案的高标准而设计。
JSONx 框架是为企业解决方案创建的,为复杂系统提供高标准的质量和实用性,并为开发人员提供易用性和编辑时错误验证。
JSD(x) 绑定引擎、处理器和验证器报告了 87% 的测试覆盖率,使 Java 开发人员能够自信地集成框架以将 JSD(x) 模式绑定到他们的 Java 应用程序,并对 JSON 文档进行编码、解码和验证。 如需详细了解 Java 的 JSONx 框架,请参阅 Java 的 JSONx 框架。
结论
通过深入了解近年来 Web 和软件趋势的历史,我们可以看到 JavaScript 的激增与 JSON 的流行之间的密切关系。 许多文章和博客文章在比较 JSON 和 XML 时提供了有限的视角,导致读者认为 XML 已经过时,并且许多人没有意识到可以帮助他们改进软件架构、软件对变化的弹性以及整体质量和软件整体的稳定性。 通过对每个标准的优缺点进行更深入的评估,开发人员可以为他们的项目做出更好的决策。
就像导致 XML 发明的 HTML 的“分歧灾难”一样,在依赖 JSON 进行数据交换的复杂代码库中也实现了类似的效果。 JSON 规范没有封装围绕数据交换的即时功能,这可能导致应用程序更高层中的逻辑碎片化。 然而,使用 XML,开发人员能够将围绕数据交换的复杂性推到应用程序的较低层,从而能够在应用程序生命周期的早期发现错误。 特别是对于编译型语言,结合绑定框架,依赖 XML 绑定的架构可以将数据相关错误的可能性降低到接近于零。 对于企业而言,正是这些系统地降低软件风险的强大功能使 XML 成为“计算的圣杯”。
JSON 将继续存在,并且有几个项目正在为向 JSON 提供强大的 XML 功能而获得动力。 JSON 模式项目提供了一个社区开发的模式规范,该规范已经有机地发展,以支持广泛的属性和声明模式来描述和约束 JSON 文档。 JSONx 项目提供了一种企业级模式语言,其设计与 XML 模式定义语言非常相似,并为 JSON 模式文档的规范提供 JSON 和 XML 格式。 借助这些规范和框架,开发人员能够降低与围绕数据交换的更高层要求相关的软件风险,例如消费者驱动的合同、协议版本控制、内容验证等。
XML 的高级特性旨在降低与标记语言相关的软件风险。 JSON 的用例也不例外,模式语言是一种经过时间考验和证明的解决方案,可以系统地对冲围绕数据交换的各种软件风险。
参考
1. JSON 与 XML(w3schools.com,2016 年 12 月)
2. XML 的全球成功(W3C,2018 年 7 月)
3. W3C - 什么是 XML 模式? (W3C,2009 年 10 月)
4. 互联网:历史百科全书。 年表,第 3 卷,p。 130 (ABC-CLIO, 2005)
5. JSON 模式(2008 年 7 月)
6. JSON 模式验证器(GitHub)
7. JsonSchema 和子类化(Horne,2016 年 3 月)