根据您定义的架构,给定的 JSON 是正确的。您的架构所说的是,对于每个 object Author
,您的 JSON 应至少有 1 个和最多 1 个字符串属性。
除此之外,属性minItems
和maxItems
专门用于数组,但在您的定义中,它们位于对象下。在底部的链接文档中阅读更多相关信息。
混淆的部分是您期望数组是对象而对象是数组,有时很难区分。
简单来说:
JSON对象是一组键:值对。就好像您正在定义一个对象(类)并在 OOP 语言中设置它的属性值。JSON对象
的基本定义:
{
"type": "object",
"properties": {
"MyString": {
"type": "string"
},
"MyInterger": {
"type": "integer"
}
}
JSON 数组是相同的,有时是相似的,对象或单个值的集合。JSON数组
的基本定义:
{
"type": "array",
"items": {
"type": "string"
}
}
还可以帮助定义何时使用什么,是考虑您想要创建的内容,但将其视为 OOP 语言中的对象。
例子:
对于以下Book
JSON object,我可以想象一个如图所示的类结构,然后从中创建架构:
JSON:
{
"Author": "First Author",
"TotalPages": 128,
"Chapters": [
{
"Number": 1,
"Heading": "Chapter One"
},
{
"Number": 2,
"Heading": "Chapter Two"
}
]
}
我们拥有的是
- 两个基本对象
Author (string)
和TotalPages (integer)
- 对象数组,其中
Chapters
包含两个基本对象Number (integer)
和Heading (string)
类表示:
public class Book
{
public string Author { get; set; }
public int TotalPages { get; set; }
// Note the array
public Chapter[] Chapters { get; set; } // Could be List<Chapter>
}
public class Chapter
{
public int Number { get; set; }
public string Heading { get; set; }
}
生成的架构:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"Author": {
"type": "string"
},
"TotalPages": {
"type": "integer"
},
"Chapters": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"Number": {
"type": "integer"
},
"Heading": {
"type": "string"
}
}
}
}
},
"required": ["Author", "Chapters"]
}
现在你会注意到我故意省略了`Books`部分,因为那是`Book`的*一个数组/集合*。如果我们想将它添加到 JSON 模式和类中,我们需要这样定义它。在此过程中,让我们还为每本书添加一个字符串数组用于“关键字”,以便清楚如何定义每个。
首先让我们更改我们想要的输出( JSON)。
我们希望我们的基础对象现在是Books
并且它应该是Book
对象的集合,所以我们将Book
对象包含在其中,[ ]
并且为了它添加另一本书。Keywords
我们还向对象添加了一个集合Book
。
{
"Books":
[
{
"Author": "First Author",
"TotalPages": 128,
"Chapters": [
{
"Number": 1,
"Heading": "Chapter One"
},
{
"Number": 2,
"Heading": "Chapter Two"
}
],
"Keywords": [
"This",
"is",
"book",
"Alpha"
]
},
{
"Author": "Second Author",
"TotalPages": 256,
"Chapters": [
{
"Number": 1,
"Heading": "Erstes Kapitel"
},
{
"Number": 2,
"Heading": "Zweites Kapitel"
}
],
"Keywords": [
"This",
"is just",
"Beta"
]
}
]
}
现在我们有以下内容:
- 一个
Books
包含我们之前定义的对象数组Book
的对象。(请注意,Book
它永远不会被命名,因为这会在 JSON 中添加另一个层次结构)
- 除了我们之前定义的对象外,我们还有一个
string
表示Keywords
让我们更改JSON 的类/对象表示,这样做将有助于了解如何修改模式。
public class MyBookCollection
{
// Note the array!!
public Book[] Books { get; set; } // Could also be List<Book>
}
public class Book
{
public string Author { get; set; }
public int TotalPages { get; set; }
// Note the arrays!!
public Chapter[] Chapters { get; set; } // Could also be List<Chapter>
public string[] Keywords { get; set; } // Could also be List<string>
}
public class Chapter
{
public int Number { get; set; }
public string Heading { get; set; }
}
我们现在知道当我们最终解析 JSON 时我们的数据和类会是什么样子。让我们更改JSON Schema,以便我们可以在验证器中使用一些东西。
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"Books": {
"type": "array",
"minItems": 1,
"maxItems": 15,
"title": "Book",
"items": {
"type": "object",
"properties": {
"Author": {
"type": "string"
},
"TotalPages": {
"type": "integer"
},
"Chapters": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"Number": {
"type": "integer"
},
"Heading": {
"type": "string"
}
}
}
},
"Keywords": {
"type": "array",
"minItems":2,
"items": {
"type": "string"
}
}
},
"required": ["Author", "Chapters"]
}
}
}
}
我添加了一些minItems
和maxItems
到数组定义中,以便您可以看到在哪里以及如何设置它们。您可以将模式和数据复制到任何验证器,并使用它们来查看它们是如何工作的。
另外一件重要的事情:
您不能通过模式验证来防止或检查对象内的重复属性。
例如,使用我们的简单 JSON 对象并添加重复属性,
{
"Author": "First Author",
"Author": "!!Duplicate Author!!",
"TotalPages": 128,
"Chapters": [
{
"Number": 1,
"Heading": "Chapter One"
},
{
"Number": 2,
"Heading": "Chapter Two"
}
]
}
将该 JSON 转储到提到的任何验证器中,它们都将验证为**正确**和**通过**。我检查并在 [JSON Schema Google Group][6] 上确认了这一点,目前无法通过模式定义对其进行检查。
重复属性的处理方式也是特定于库的。
例如,用于 C# 的Newtonsoft.Json和ServiceStack库都将使用属性的最后一次出现。
因此,在我们的示例中,Book.Author
使用任一库反序列化后的属性值将是“!!Duplicate Author!!”。
一些资料来源: