如果您在输入文件中指定配置为架构中要求的元素,则验证正常。 如果您附加“maxItems”:1,它并不关心您是否在输入文件中添加另一个元素,验证器仍然将其视为有效的输入文件。
即: 架构:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"Books": {
"type": "object",
"minItems": 1,
"properties": {
"Book": {
"type": "object",
"minItems": 1,
"maxItems": 1,
"properties": {
"Author": {
"type": "string",
"minItems": 1,
"maxItems": 1
}
},
"required": ["Author"]
}
},
"required": ["Book"]
}
},
"required": ["Books"]
}
输入文件:
{
"Books": {
"Book": {
"Author": "Andreas",
"Author": "Geir"
}
}
}
这不应该是一个无效的输入文件吗?
验证者:
根据您定义的架构,给定的 JSON 是正确的。 您的架构所说的是,对于每个对象
Author
,应该至少有 1 个、最多 1 个字符串属性,您的 JSON 符合这一点。minItems
和 maxItems
专门用于 arrays,但在您的定义中,它们位于 objects 下。请在底部的链接文档中阅读更多相关信息。
令人困惑的部分是您期望数组是对象,而对象是数组,这有时很难区分。
简单来说:
JSON 对象 是key:value 对的集合。这就好像您正在定义一个对象(类)并用 OOP 语言设置它的属性值。
JSON 对象的基本定义:
{
"type": "object",
"properties": {
"MyString": {
"type": "string"
},
"MyInterger": {
"type": "integer"
}
}
JSON 数组是相同(有时是相似)对象或单个值的集合。
JSON 数组的基本定义:
{
"type": "array",
"items": {
"type": "string"
}
}
还可以帮助定义何时使用什么,那就是想想你想要创建什么,但作为 OOP 语言中的对象。
示例:
对于以下
Book
JSON 对象,我可以想象一个如图所示的类结构,然后从中创建架构:
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"]
}
首先让我们更改所需的输出(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 的 class/object 表示形式,这样做将有助于了解如何修改架构。
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 时,我们的 data 和 class 会是什么样子。让我们更改 JSON 架构,以便我们拥有可以在验证器中使用的东西。
{
"$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"
}
]
}
如何处理重复属性也是特定于库的。
例如,C# 的 Newtonsoft.Json 和 ServiceStack 库都将使用最后一次出现的属性。
因此,从我们的示例来看,使用任一库反序列化后
Book.Author
属性的值将是“!!重复作者!!”。
一些来源: