如果你曾经使用过 XML Schema、RelaxNG 或 ASN.1,你可能已经知道模式是什么,并且可以愉快地跳到下一节。如果这一切对你来说听起来像胡言乱语,那么你来到正确的地方。要定义什么是 JSON Schema,我们可能首先应该定义什么是 JSON。
JSON 代表“JavaScript 对象表示法”,是一种简单的數據交换格式。它最初是为万维网而设计的。由于 JavaScript 存在于大多数 Web 浏览器中,而 JSON 基于 JavaScript,因此在浏览器中非常容易支持。然而,它已经证明足够有用,足够简单,因此现在它被用于许多不涉及 Web 浏览的其他上下文中。
本质上,JSON 是建立在以下数据结构上的
对象
{ "key1": "value1", "key2": "value2" }
数组
[ "first", "second", "third" ]
数字
字符串
布尔值
空值
这些类型在大多数编程语言中都有对应。
通过这些简单的数据类型,可以表示各种结构化数据。然而,伴随着这种强大的灵活性的是巨大的责任,因为同一个概念可以以无数种方式表示。例如,你可以想象用 JSON 以不同的方式表示有关一个人的信息
{ "name": "George Washington", "birthday": "February 22, 1732", "address": "Mount Vernon, Virginia, United States"}
{ "first_name": "George", "last_name": "Washington", "birthday": "1732-02-22", "address": { "street_address": "3200 Mount Vernon Memorial Highway", "city": "Mount Vernon", "state": "Virginia", "country": "United States" }}
两种表示方法都同样有效,尽管其中一种明显比另一种更正式。记录的设计很大程度上取决于它在应用程序中的预期用途,因此这里没有正确或错误的答案。但是,当应用程序说“给我一个人员的 JSON 记录”时,重要的是要知道该记录应该如何组织。例如,我们需要知道期望哪些字段以及值如何表示。这就是 JSON Schema 的作用。以下 JSON Schema 片段描述了上面的第二个示例的结构。现在不要太担心细节。将在后续章节中解释这些细节。
schema
{ "type": "object", "properties": { "first_name": { "type": "string" }, "last_name": { "type": "string" }, "birthday": { "type": "string", "format": "date" }, "address": { "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" }, "country": { "type" : "string" } } } }}
通过将第一个示例“验证”到此模式,您可以看到它失败了
{ "name": "George Washington", "birthday": "February 22, 1732", "address": "Mount Vernon, Virginia, United States"}
不符合模式
但是,第二个示例通过了
{ "first_name": "George", "last_name": "Washington", "birthday": "1732-02-22", "address": { "street_address": "3200 Mount Vernon Memorial Highway", "city": "Mount Vernon", "state": "Virginia", "country": "United States" }}
符合模式
您可能已经注意到,JSON Schema 本身是用 JSON 编写的。它本身是数据,而不是计算机程序。它只是一个用于“描述其他数据结构”的声明性格式。这是它的优点也是它的缺点(它与其他类似的模式语言共享此特点)。它可以轻松地简洁地描述数据的表面结构,并自动根据该结构验证数据。但是,由于 JSON Schema 不能包含任意代码,因此数据元素之间某些关系无法表达。因此,任何针对足够复杂数据格式的“验证工具”可能都会包含两个验证阶段:一个在模式(或结构)级别,另一个在语义级别。后一种检查可能需要使用更通用的编程语言来实现。