В соответствии с вашей определенной схемой данный JSON является правильным. Ваша схема говорит о том, что для каждого объекта Author
должно быть минимум 1 и максимум 1 строковое свойство, которому соответствует ваш JSON.
Кроме того, свойства minItems
и maxItems
предназначены специально для массивов, но в вашем определении они относятся к объектам. Подробнее об этом читайте в связанной документации внизу.
Часть, где возникает путаница, заключается в том, что вы ожидаете, что массивы будут объектами, а объекты будут массивами, которые иногда бывает трудно различить.
Проще говоря:
объект JSON – это набор пар ключ:значение. Это было бы так, как если бы вы определяли объект (класс) и задавали значения его свойств на языке ООП.
Базовое определение объекта JSON:
{
"type": "object",
"properties": {
"MyString": {
"type": "string"
},
"MyInterger": {
"type": "integer"
}
}
Массив JSON – это набор одинаковых, иногда похожих объектов или отдельных значений.
Основное определение массива JSON:
{
"type": "array",
"items": {
"type": "string"
}
}
Что также может помочь определить, что и когда использовать, — это думать о том, что вы хотите создать, но как об объекте на языке ООП.
Пример:
Для следующего 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"]
}
Теперь вы заметите, что я намеренно пропустил раздел Books
, так как это массив/коллекция Book
. Если мы хотим добавить это в схему и класс JSON, нам нужно будет определить это как таковое. Пока мы на этом, давайте также добавим массив строк для каждой книги для Keywords
, чтобы было ясно, как можно определить каждую.
Во-первых, давайте изменим желаемый результат (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": "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 в любой из упомянутых валидаторов, все они будут проверены как правильные и пройденные. Я проверил, и это подтверждено в группе Google схемы JSON. что его нельзя проверить в настоящее время с помощью определения схемы.
Как обрабатываются повторяющиеся свойства, также зависит от библиотеки.
Например, как Newtonsoft Библиотеки .Json и ServiceStack для C# будут использовать последнее вхождение свойства.
Итак, from В нашем примере значение свойства Book.Author
после десериализации с любой библиотекой будет "!!Дубликат автора!!".
Некоторые источники:
person
Bernd Linde
schedule
07.05.2015