Понимание схемы JSON (JSON Schema), часть 1

08.11.21

Интеграция - Файловый обмен (TXT, XML, DBF), FTP

Перевод книги https://json-schema.org/understanding-json-schema/

Схема JSON - это мощный инструмент для проверки структуры данных JSON. Однако научиться использовать его, прочитав его спецификацию, все равно что научиться водить автомобиль, глядя на его чертежи. Вам не нужно знать, как сочетается электродвигатель, если все, что вы хотите сделать, это съездить за продуктами. Поэтому эта книга призвана стать дружелюбным инструктором по вождению для схемы JSON. Это для тех, кто хочет написать и понять его, но, возможно, не заинтересован в создании собственного системы поддержки или написании собственного средства проверки схемы JSON - пока.

Примечание: В этой книге описывается проект схемы JSON 2020-12. Более ранние версии схемы JSON не полностью совместимы с форматом, описанным здесь, но по большей части эти различия отмечены в тексте.

 

Соглашения, используемые в этой книге

Примечания, относящиеся к конкретному языку

Имена основных типов в JavaScript и JSON могут сбивать с толку при использовании другого динамического языка (далее автор пишет что в основном использует Python).

Примечание: Примеры переделаны под 1С, версия 8.3.6+, до этого использовалась библиотека в виде общего модуля.

 

Примечания по конкретным версиям проекта

Стандарт схемы JSON прошел через ряд изменений или "черновиков" (draft). Текущая версия - проект (Draft) 2020-12, но некоторые более старые проекты по-прежнему широко используются.

Примечание: В переводе частично буду использовать "версия" вместо "проект".

Текст написан для поощрения использования проекта 2020-12 и отдает приоритет последним соглашениям и функциям, но там, где он отличается от предыдущих проектов, эти различия подчеркиваются в специальных примечаниях. Если вы хотите ориентироваться только на проект 2020-12, вы можете смело игнорировать эти разделы.

 

Примеры

В этой книге приведено множество примеров, и все они соответствуют одному и тому же формату. В начале каждого примера приведена краткая схема JSON, иллюстрирующая определенный принцип, за которой следуют короткие фрагменты JSON, которые либо допустимы, либо недопустимы для этой схемы. Допустимые примеры выделены зеленым цветом с галочкой. Недопустимые примеры выделены красным цветом с крестиком. Часто между ними есть комментарии, объясняющие, почему что-то является или не является действительным.

Примечание: Эти примеры автоматически проверяются при создании книги (оригинал написан с помощью LaTeX + Sphinx), так что, надеюсь, они не только полезны, но и правильны!

Например, вот фрагмент, иллюстрирующий, как использовать тип число (number):

{ "type": "number" }
42
-1

Простое число с плавающей запятой:

5.0

Экспоненциальная запись также работает:

2.99792458e8

Числа в виде строк отклоняются:

"42"

 

Что такое схема?

Если вы когда-либо использовали XML-схему, RelaxNG или ASN.1, вы, вероятно, уже знаете, что такое схема, и можете с радостью перейти к следующему разделу. Если все это звучит для вас как чушь собачья, вы пришли по адресу. Чтобы определить, что такое схема JSON, нам, вероятно, следует сначала определить, что такое JSON.

JSON расшифровывается как "Обозначение объектов JavaScript" (JavaScript Object Notation), простой формат обмена данными. Это началось как обозначение для всемирной паутины. Поскольку JavaScript существует в большинстве веб-браузеров, а JSON основан на JavaScript, его очень легко поддерживать. Тем не менее, он оказался достаточно полезным и достаточно простым, что теперь он используется во многих других контекстах, которые не связаны с веб-серфингом.

В своей основе JSON построен на следующих структурах данных:

объект (object)

{ "key1": "value1", "key2": "value2" }

массив (array)

[ "first", "second", "third" ]

число (number)

42
3.1415926

строка (string)

"This is a string"

булево (boolean)

true
false

null

null

 

Эти типы имеют аналоги в большинстве языков программирования, хотя они могут называться по-разному.

Следующая таблица сопоставляет имена типов JSON с их аналогичными типами в 1C:

JSON 1C
объект (object) Соответствие (Структура)
массив (array) Массив
число (number) Число
строка (string) Строка
булево (boolean) Булево
null Null

 

С помощью этих простых типов данных могут быть представлены все виды структурированных данных. Однако с такой большой гибкостью приходит большая ответственность, поскольку одна и та же концепция может быть представлена множеством способов. Например, вы могли бы представить представление информации о человеке в 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. Следующий фрагмент схемы JSON описывает, как структурирован второй приведенный выше пример. Пока не беспокойтесь слишком сильно о деталях. Они объясняются в последующих главах.

{
  "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 написана в JSON. Это сами данные, а не компьютерная программа. Это просто декларативный формат для “описания структуры других данных”. В этом его сила и его слабость (которую он разделяет с другими аналогичными языками схем). Легко кратко описать поверхностную структуру данных и автоматизировать проверку данных по ней. Однако, поскольку схема JSON не может содержать произвольный код, существуют определенные ограничения на отношения между элементами данных, которые невозможно выразить. Поэтому любой “инструмент проверки” для достаточно сложного формата данных, скорее всего, будет иметь два этапа проверки: один на уровне схемы (или структуры) и один на семантическом уровне. Последняя проверка, вероятно, должна быть реализована с использованием более универсального языка программирования.

 

Основы

В "Что такое схема?" мы описали, что такое схема, и, надеюсь, обосновали необходимость языков схем. Здесь мы приступаем к написанию простой схемы JSON.

Привет, Мир!

При изучении любого нового языка часто бывает полезно начать с самого простого из возможных. В схеме JSON пустой объект является полностью допустимой схемой, которая будет принимать любой допустимый JSON.

{ }

Это принимает все, что угодно, если это действительный JSON

42
"I'm a string"
{ "an": [ "arbitrarily", "nested" ], "data": "structure" }>

Вы также можете использовать значение true вместо пустого объекта для представления схемы, которая соответствует чему-либо, или значение false для схемы, которая ничему не соответствует.

true

Это принимает все, что угодно, если это действительный JSON

42
"I'm a string"
{ "an": [ "arbitrarily", "nested" ], "data": "structure" }
false
"Resistance is futile...  This will always fail!!!"

 

Ключевое слово "тип" (type)

Конечно, мы бы не использовали схему JSON, если бы хотели просто принять любой документ JSON. Наиболее распространенное действие в схеме JSON - это ограничение определенным типом. Для этого используется ключевое слово "type".

Примечание: Когда в этой книге говорится о схеме JSON “ключевые слова”, это означает “ключевую” часть пары ключ/значение в объекте. Большая часть работы по написанию схемы JSON включает сопоставление специального “ключевого слова” со значением внутри объекта.

{ "type": "string" }
"I'm a string"
42

Ключевое слово "тип" более подробно описано в разделе "Ключевые слова для конкретного типа".

 

Объявление схемы JSON

Не всегда легко определить, какой проект использует схема JSON. Вы можете использовать ключевое слово "$schema", чтобы указать, в какую версию спецификации схемы JSON записана схема. Дополнительные сведения см. в разделе "$schema". Обычно рекомендуется включать его, хотя это и не требуется.

Примечание: Для краткости ключевое слово "$schema" не включено в большинство примеров в этой книге, но его всегда следует использовать в реальном мире.

{ "$schema": "https://json-schema.org/draft/2020-12/schema" }

 

Объявление уникального идентификатора

Также рекомендуется включать свойство $id в качестве уникального идентификатора для каждой схемы. На данный момент просто установите для него URL-адрес в домене, которым вы управляете, например:

{ "$id": "http://yourdomain.com/schemas/myschema.json" }

Детали "$id" станут более очевидными, когда вы начнете структурировать сложную схему.

 

Описание схемы JSON

Ключевые слова, зависящие от типа

Ключевое слово type является основополагающим для схемы JSON. Он определяет тип данных для схемы.

По своей сути схема JSON определяет следующие основные типы, дублирует данные из раздела "Что такое схема?".

Ключевое слово type может быть строкой или массивом:

  • Если это строка, то это имя одного из основных типов, описанных выше.
  • Если это массив, то это должен быть массив строк, где каждая строка является именем одного из основных типов, и каждый элемент уникален. В этом случае фрагмент JSON допустим, если он соответствует любому из заданных типов.

Вот простой пример использования ключевого слова type:

{ "type": "number" }
42
42.0

Это не число, это строка, содержащая число.

"42"

В следующем примере мы принимаем строки и числа, но не структурированные типы данных:

{ "type": ["number", "string"] }
42
"Life, the universe, and everything"
["Life", "the universe", "and everything"]

Для каждого из этих типов существуют ключевые слова, которые применимы только к этим типам. Например, числовые типы имеют способ указания числового диапазона, который не был бы применим к другим типам. В этой ссылке эти ключевые слова проверки описываются вместе с каждым из их соответствующих типов в следующих главах.

 

Строки

Тип строка (string) используется для строк текста. Он может содержать символы Юникода.

{ "type": "string" }
"This is a string"

Символы Юникода:

"Déjà vu"
""
"42"
42

 

Длина

Длину строки можно ограничить с помощью ключевых слов minLength и maxLength. Для обоих ключевых слов значение должно быть неотрицательным числом.

{
  "type": "string",
  "minLength": 2,
  "maxLength": 3
}
"A"
"AB"
"ABC"
"ABCD"

 

Регулярные Выражения

Ключевое слово pattern используется для ограничения строки определенным регулярным выражением. Синтаксис регулярных выражений определен в JavaScript (в частности, ECMA 262) с поддержкой Юникода. Дополнительные сведения см. в разделе Регулярные выражения.

Примечание: При определении регулярных выражений важно отметить, что строка считается допустимой, если выражение совпадает в любом месте строки. Например, регулярное выражение "p" будет соответствовать любой строке с буквой "p" в ней, например "apple", а не просто строке, которая просто "p". Поэтому, как правило, менее запутанно, как само собой разумеющееся, заключать регулярное выражение в ^...$, например, "^p$", если только нет веской причины не делать этого.

Детальный разбор в отдельной подглаве.

 

Форматы

Ключевое слово format позволяет выполнять базовую семантическую идентификацию определенных типов строковых значений, которые обычно используются. Например, поскольку в JSON нет типа “Дата-время”, даты должны быть закодированы в виде строк. формат позволяет автору схемы указать, что строковое значение следует интерпретировать как дату. По умолчанию формат является просто аннотацией и не влияет на проверку.

При необходимости реализации средства проверки могут предоставлять опцию конфигурации, позволяющую использовать формат в качестве утверждения, а не просто аннотации. Это означает, что проверка завершится неудачей, если, например, значение с форматом "date" не находится в форме, которую можно проанализировать как дату. Это может позволить ограничить значения сверх того, что могут делать другие инструменты в схеме JSON, включая регулярные выражения.

Примечание: Реализации могут обеспечивать проверку только для подмножества встроенных форматов или выполнять частичную проверку для данного формата. Например, в некоторых реализациях строка может считаться электронной почтой, если она содержит @, в то время как в других может потребоваться дополнительная проверка других аспектов правильно сформированного адреса электронной почты.

В спецификации схемы JSON существует уклон в сторону сетевых форматов, скорее всего, из-за ее наследия в веб-технологиях. Однако могут также использоваться пользовательские форматы, если стороны, обменивающиеся документами JSON, также обмениваются информацией о типах пользовательских форматов. Средство проверки схемы JSON будет игнорировать любой тип формата, который он не понимает.

 

Встроенные форматы

Ниже приведен список форматов, указанных в спецификации схемы JSON.

Даты и время

Даты и время представлены в RFC 3339, раздел 5.6. Это подмножество формата даты, также широко известного как формат ISO 8601.

  • "date-time" - Дата и время вместе, например "2018-11-13T20:20:39+00:00"
  • "time" - Время, например "20:20:39+00:00"
  • "date" - Дата, например "2018-11-13"
  • "duration" - Продолжительность, определенная стандартом ISO 8601 ABNF для "duration". Например, P3D выражает продолжительность в 3 дня.

Адреса электронной почты

  • "email" - Адрес электронной почты в Интернете, см. RFC 5321, раздел 4.1.2.
  • "idn-email" - Интернационализированная форма адреса электронной почты в Интернете, см. RFC 6531.

Имена хостов

  • "hostname" - Имя хоста в Интернете, см. RFC 1123, раздел 2.1.
  • "idn-hostname" - Интернационализированное имя хоста в Интернете, см. RFC5890, раздел 2.3.2.3.

IP-адреса

  • "ipv4" - Адрес IPv4, в соответствии с синтаксисом ABNF с пунктирными квадратами, как определено в RFC 2673, раздел 3.2.
  • "ipv6" - Адрес IPv6, как определено в RFC 2373, раздел 2.2.

Идентификаторы ресурсов

  • "uuid" - Универсальный уникальный идентификатор, как определено в RFC 4122. Пример: 3e4666bf-d5e5-4aa7-b8ce-cefe41c7568a
  • "uri" - Универсальный идентификатор ресурса (URI), согласно RFC 3986.
  • "uri-reference" - Ссылка на URI (либо URI, либо относительная ссылка), в соответствии с RFC 3986, раздел 4.1.
  • "iri" - Интернационализированный эквивалент "uri", согласно RFC3987.
  • "iri-reference" - Интернационализированный эквивалент "uri-reference", согласно RFC3987

Если значения в схеме могут быть привязаны к определенному исходному пути (например, к ссылке с веб-страницы), обычно лучше использовать "uri-reference" (или "iri-reference"), а не "uri" (или "iri"). "uri" следует использовать только тогда, когда путь должен быть абсолютным.

Шаблон URI

  • "uri-template" - Шаблон URI (любого уровня) в соответствии с RFC6570. Если вы еще не знаете, что такое шаблон URI, вам, вероятно, это значение не нужно.

Указатель JSON

  • "json-pointer" - Указатель JSON, согласно RFC 6901. Существует более подробное обсуждение использования указателя JSON в схеме JSON при структурировании сложной схемы. Обратите внимание, что это следует использовать только в том случае, если вся строка содержит только содержимое JSONPointer, например /foo/bar. Фрагменты URI указателя JSON, например #/foo/bar/, должны использовать "uri-reference".
  • "relative-json-pointer" - см. Относительный указатель JSON.

Регулярные Выражения

  • "regex" - Регулярное выражение, которое должно быть допустимым в соответствии с диалектом ECMA 262.

Будьте осторожны, на практике от валидаторов схемы JSON требуется только принимать безопасное подмножество регулярных выражений, описанных в другом месте этого документа.

 

Регулярные Выражения

Ключевые слова шаблон и Свойства шаблона используют регулярные выражения для выражения ограничений. Используемый синтаксис регулярных выражений взят из JavaScript (в частности, ECMA 262). Однако этот полный синтаксис широко не поддерживается, поэтому рекомендуется придерживаться подмножества этого синтаксиса, описанного ниже.

Один символ юникода (кроме специальных символов ниже) соответствует самому себе.

  • .: Соответствует любому символу, кроме символов разрыва строки. (Имейте в виду, что то, что представляет собой символ разрыва строки, в некоторой степени зависит от вашей платформы и языковой среды, но на практике это редко имеет значение).
  • ^: Совпадает только в начале строки.
  • $: Совпадает только в конце строки.
  • (...): Сгруппируйте ряд регулярных выражений в одно регулярное выражение.
  • |: Соответствует регулярному выражению, предшествующему или следующему за символом |.
  • [abc]: Соответствует любому из символов внутри квадратных скобок.
  • [a-z]: Соответствует диапазону символов.
  • [^abc]: Соответствует любому символу, не указанному в списке.
  • [^a-z]: Соответствует любому символу за пределами диапазона.
  • +: Соответствует одному или нескольким повторениям предыдущего регулярного выражения.
  • *: Соответствует нулю или более повторений предыдущего регулярного выражения.
  • ?: Соответствует нулю или одному повторению предыдущего регулярного выражения.
  • +?, *?, ??: *, +, и? квалификаторы все жадные; они соответствуют как можно большему количеству текста. Иногда такое поведение нежелательно, и вы хотите сопоставить как можно меньше символов.
  • (?!x), (?=x): Отрицательный и положительный внешний вид.
  • {x}: Соответствует точно x вхождениям предыдущего регулярного выражения.
  • {x,y}: Соответствует по крайней мере x и не более y вхождениям предыдущего регулярного выражения.
  • {x,}: Сопоставьте x или более вхождений предыдущего регулярного выражения.
  • {x}?, {x,y}?, {x,}?: Ленивые версии приведенных выше выражений.

Пример

В следующем примере сопоставляется простой североамериканский телефонный номер с дополнительным кодом города:

{
   "type": "string",
   "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$"
}
"555-1212"
"(888)555-1212"
"(888)555-1212 ext. 532"
"(800)FLOWERS"

 

Числовые типы

В схеме JSON есть два числовых типа: целое число(integer) и число(number). Они используют одни и те же ключевые слова проверки.

Примечание: В JSON нет стандартного способа представления комплексных чисел, поэтому нет способа проверить их в схеме JSON.

 

integer

Целочисленный тип используется для целых чисел. JSON не имеет различных типов для целых чисел и значений с плавающей запятой. Поэтому наличия или отсутствия десятичной точки недостаточно, чтобы различать целые и нецелые числа. Например, 1 и 1.0 - это два способа представления одного и того же значения в JSON. Схема JSON считает это значение целым числом независимо от того, какое представление было использовано.

{ "type": "integer" }
42
-1

Числа с нулевой дробной частью считаются целыми числами

1.0

Числа с плавающей запятой отклоняются:

3.1415926

Числа в виде строк отклоняются:

"42"

 

number

Тип number используется для любого числового типа, будь то целые числа или числа с плавающей запятой.

{ "type": "number" }
42
-1

Простое число с плавающей запятой:

5.0

Экспоненциальная запись также работает:

2.99792458e8

Числа в виде строк отклоняются:

"42"

 

Кратность

Числа могут быть ограничены кратным заданному числу, используя ключевое слово multipleOf. Он может быть установлен на любое положительное число.

{
    "type": "number",
    "multipleOf" : 10
}
0
10
20

Не кратно 10:

23

 

Диапазон

Диапазоны чисел задаются с использованием комбинации minimum и maximum ключевых слов (или exclusiveMinimum
и exclusiveMaximum для выражения исключения из диапазона).

Если x - это проверяемое значение, то должно выполняться следующее:

  • x ≥ minimum
  • x > exclusiveMinimum
  • x ≤ maximum
  • x < exclusiveMaximum
{
  "type": "number",
  "minimum": 0,
  "exclusiveMaximum": 100
}

Меньше минимального:

-1

минимум включен, поэтому допустимо значение 0:

0
10
99

exclusiveMaximum является исключающим, поэтому 100 не является действительным:

100

 

Объекты

Объекты - это тип отображения в JSON. Они сопоставляют "ключи" с "значениями". В JSON "ключи" всегда должны быть строками. Каждая из этих пар условно называется "свойством".

{ "type": "object" }
{
   "key": "value",
   "another_key": "another_value"
}
{
    "Sun": 1.9891e30,
    "Jupiter": 1.8986e27,
    "Saturn": 5.6846e26,
    "Neptune": 10.243e25,
    "Uranus": 8.6810e25,
    "Earth": 5.9736e24,
    "Venus": 4.8685e24,
    "Mars": 6.4185e23,
    "Mercury": 3.3022e23,
    "Moon": 7.349e22,
    "Pluto": 1.25e22
}

Использование нестроковых файлов в качестве ключей недопустимо в JSON:

{
    0.01: "cm",
    1: "m",
    1000: "km"
}
"Not an object"
["An", "array", "not", "an", "object"]

 

Свойства

Свойства (пары ключ-значение) объекта определяются с помощью ключевого слова properties. Значение свойств - это объект, где каждый ключ - это имя свойства, а каждое значение - схема, используемая для проверки этого свойства. Любое свойство, которое не соответствует ни одному из имен свойств в ключевом слове properties, игнорируется этим ключевым словом.

Примечание: См. Дополнительные свойства и Недооцененные свойства, чтобы узнать, как запретить свойства, которые не соответствуют ни одному из имен свойств в свойствах.

Например, предположим, что мы хотим определить простую схему для адреса, состоящего из номера, названия улицы и типа улицы:

{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
  }
}
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }

Если мы введем номер неверным типом, он будет недействительным:

{ "number": "1600", "street_name": "Pennsylvania", "street_type": "Avenue" }

По умолчанию допустимо не указывать свойства. См. раздел Необходимые свойства.

{ "number": 1600, "street_name": "Pennsylvania" }

В широком смысле даже пустой объект является допустимым:

{ }

По умолчанию допустимо использование дополнительных свойств:

{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }

Шаблоны Свойств

Иногда вы хотите сказать, что, учитывая определенный тип имени свойства, значение должно соответствовать определенной схеме. Вот тут-то и пригодятся patternProperties: он отображает регулярные выражения в схемы. Если имя свойства соответствует заданному регулярному выражению, значение свойства должно быть проверено на соответствие соответствующей схеме.

Примечание: Регулярные выражения не привязаны. Это означает, что при определении регулярных выражений для свойств шаблона важно отметить, что выражение может совпадать в любом месте имени свойства. Например, регулярное выражение "p" будет соответствовать любому имени свойства с буквой "p" в нем, например "apple", а не только свойству, имя которого просто "p". Поэтому обычно менее запутанно заключать регулярное выражение в ^...$, например, "^p$".

В этом примере любые свойства, имена которых начинаются с префикса S_, должны быть строками, а любые свойства с префиксом I_ должны быть целыми числами. Любые свойства, которые не соответствуют ни одному из регулярных выражений, игнорируются.

{
  "type": "object",
  "patternProperties": {
    "^S_": { "type": "string" },
    "^I_": { "type": "integer" }
  }
}
{ "S_25": "This is a string" }
{ "I_0": 42 }

Если имя начинается с S_, оно должно быть строкой

{ "S_0": 42 }

Если имя начинается с I_, оно должно быть целым числом

{ "I_42": "This is a string" }

Это ключ, который не соответствует ни одному из регулярных выражений:

{ "keyword": "value" }

 

Дополнительные Свойства

Ключевое слово additionalProperties используется для управления обработкой дополнительных элементов, то есть свойств, имена которых не указаны в ключевом слове properties или не соответствуют ни одному из регулярных выражений в ключевом слове patternProperties. По умолчанию любые дополнительные свойства разрешены.

Значение ключевого слова дополнительные свойства - это схема, которая будет использоваться для проверки любых свойств в экземпляре, которые не соответствуют свойствам или свойствам шаблона. Установка для схемы additionalPropertiesзначения false означает, что никакие дополнительные свойства не будут разрешены.

Повторно используйте пример из раздела "Свойства", но на этот раз установите для additionalProperties значение false.

{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
  },
  "additionalProperties": false
}
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }

Поскольку additionalProperties имеет значение false, это дополнительное свойство "direction" делает объект недействительным:

{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }

Вы можете использовать не булевы схемы для наложения более сложных ограничений на дополнительные свойства экземпляра. Например, можно разрешить дополнительные свойства, но только если каждое из них является строкой:

{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
  },
  "additionalProperties": { "type": "string" }
}
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }

Это допустимо, так как значение дополнительного свойства является строкой:

{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }

Это недопустимо, так как значение дополнительного свойства не является строкой:

{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "office_number": 201 }

Вы можете использовать additionalProperties с комбинацией properties и patternProperties. В следующем примере на основе примера из Свойств шаблона мы добавляем "builtin" свойство, которое должно быть числом, и объявляем, что все дополнительные свойства (которые не определены properties и не сопоставлены patternProperties) должны быть строками:

{
  "type": "object",
  "properties": {
    "builtin": { "type": "number" }
  },
  "patternProperties": {
    "^S_": { "type": "string" },
    "^I_": { "type": "integer" }
  },
  "additionalProperties": { "type": "string" }
}
{ "builtin": 42 }

Это ключ, который не соответствует ни одному из регулярных выражений:

{ "keyword": "value" }

Это должна быть строка:

{ "keyword": 42 }

 

Обязательные свойства

По умолчанию свойства, определенные ключевым словом properties, не требуются. Однако можно предоставить список необходимых свойств, используя ключевое слово "required".

Ключевое слово "required" принимает массив из нуля или более строк. Каждая из этих строк должна быть уникальной.

В следующем примере схемы, определяющей запись пользователя, мы требуем, чтобы у каждого пользователя было имя и адрес электронной почты, но мы не возражаем, если они не укажут свой адрес или номер телефона:

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "email": { "type": "string" },
    "address": { "type": "string" },
    "telephone": { "type": "string" }
  },
  "required": ["name", "email"]
}
{
  "name": "William Shakespeare",
  "email": "bill@stratford-upon-avon.co.uk"
}

Предоставление дополнительных свойств - это нормально, даже свойств, не определенных в схеме:

{
  "name": "William Shakespeare",
  "email": "bill@stratford-upon-avon.co.uk",
  "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England",
  "authorship": "in question"
}

Отсутствие требуемого свойства "email" делает документ JSON недействительным:

{
  "name": "William Shakespeare",
  "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England",
}

В JSON свойство со значением null не эквивалентно отсутствию свойства. Это не удается, потому что null не имеет типа "строка", он имеет тип "null"

{
  "name": "William Shakespeare",
  "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England",
  "email": null
}

 

Имена свойств

Имена свойств могут быть проверены на соответствие схеме, независимо от их значений. Это может быть полезно, если вы не хотите применять определенные свойства, но хотите убедиться, что имена этих свойств соответствуют определенному соглашению. Например, вы можете потребовать, чтобы все имена были допустимыми маркерами ASCII, чтобы их можно было использовать в качестве атрибутов на определенном языке программирования.

{
  "type": "object",
  "propertyNames": {
    "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
  }
}
{
  "_a_proper_token_001": "value"
}
{
  "001 invalid": "value"
}

Поскольку ключи объектов в любом случае всегда должны быть строками, подразумевается, что схема, указанная для propertyNames, всегда, по крайней мере:

{ "type": "string" }

 

Размер

Количество свойств объекта можно ограничить с помощью ключевых слов minProperties и maxProperties. Каждое из них должно быть неотрицательным целым числом.

{
  "type": "object",
  "minProperties": 2,
  "maxProperties": 3
}
{}
{ "a": 0 }
{ "a": 0, "b": 1 }
{ "a": 0, "b": 1, "c": 2 }
{ "a": 0, "b": 1, "c": 2, "d": 3 }

 

Массивы

Массивы используются для упорядоченных элементов. В JSON каждый элемент массива может быть разного типа.

{ "type": "array" }
[1, 2, 3, 4, 5]
[3, "different", { "types" : "of values" }]
{"Not": "an array"}

Массивы обычно используются в JSON двумя способами:

  • Проверка списка: последовательность произвольной длины, в которой каждый элемент соответствует одной и той же схеме.
  • Проверка кортежа: последовательность фиксированной длины, в которой каждый элемент может иметь разную схему. При таком использовании индекс (или местоположение) каждого элемента имеет значение в отношении того, как интерпретируется значение.

Элементы

Проверка списка полезна для массивов произвольной длины, где каждый элемент соответствует одной и той же схеме. Для такого типа массива задайте ключевое слово items для одной схемы, которая будет использоваться для проверки всех элементов в массиве.

В следующем примере мы определяем, что каждый элемент массива является числом:

{
  "type": "array",
  "items": {
    "type": "number"
  }
}
[1, 2, 3, 4, 5]

Один "не-номер" приводит к тому, что весь массив становится недействительным:

[1, 2, "3", 4, 5]

Пустой массив всегда действителен:

[]

Проверка кортежа

Проверка кортежей полезна, когда массив представляет собой набор элементов, каждый из которых имеет свою схему, и порядковый индекс каждого элемента имеет смысл.

Например, вы можете указать адрес улицы, такой как:

1600 Pennsylvania Avenue NW

как формы из 4 кортежей:

[number, street_name, street_type, direction]

Каждое из этих полей будет иметь свою схему:

  • number: Номер адреса. Должно быть, это число.
  • street_name: Название улицы. Должно быть, это струна.
  • street_type: Тип улицы. Должна быть строка из фиксированного набора значений.
  • direction: Городской сектор адреса. Должна быть строка из другого набора значений.

Для этого мы используем ключевое слово prefixItems. prefixItems - это массив, где каждый элемент представляет собой схему, соответствующую каждому индексу массива документа. То есть массив, в котором первый элемент проверяет первый элемент входного массива, второй элемент проверяет второй элемент входного массива и т.д.

{
  "type": "array",
  "prefixItems": [
    { "type": "number" },
    { "type": "string" },
    { "enum": ["Street", "Avenue", "Boulevard"] },
    { "enum": ["NW", "NE", "SW", "SE"] }
  ]
}
[1600, "Pennsylvania", "Avenue", "NW"]

"Драйв" не относится к числу приемлемых типов улиц:

[24, "Sussex", "Drive"]

В этом адресе отсутствует номер улицы

["Palais de l'Élysée"]

Это нормально, если вы не указываете все элементы:

[10, "Downing", "Street"]

И, по умолчанию, также можно добавлять дополнительные элементы в конец:

[1600, "Pennsylvania", "Avenue", "NW", "Washington"]

 

Дополнительные элементы

Ключевое слово items можно использовать для определения того, допустимо ли наличие дополнительных элементов в кортеже сверх того, что определено в prefixItems. Значение ключевого слова items - это схема, которую должны передавать все дополнительные элементы для проверки ключевого слова.

Здесь мы повторно используем схему примера выше, но установим для элементов значение false, что приведет к запрету дополнительных элементов в кортеже.

{
  "type": "array",
  "prefixItems": [
    { "type": "number" },
    { "type": "string" },
    { "enum": ["Street", "Avenue", "Boulevard"] },
    { "enum": ["NW", "NE", "SW", "SE"] }
  ],
  "items": false
}
[1600, "Pennsylvania", "Avenue", "NW"]

Это нормально, если вы не указываете все элементы:

[1600, "Pennsylvania", "Avenue"]

Но, поскольку items являются false, мы не можем предоставить дополнительные элементы:

[1600, "Pennsylvania", "Avenue", "NW", "Washington"]

Вы можете выразить более сложные ограничения, используя не булеву схему, чтобы ограничить, какое значение могут иметь дополнительные элементы. В этом случае мы могли бы сказать, что дополнительные элементы разрешены, если все они являются строками:

{
  "type": "array",
  "prefixItems": [
    { "type": "number" },
    { "type": "string" },
    { "enum": ["Street", "Avenue", "Boulevard"] },
    { "enum": ["NW", "NE", "SW", "SE"] }
  ],
  "items": { "type": "string" }
}

Дополнительные строковые элементы в порядке …

[1600, "Pennsylvania", "Avenue", "NW", "Washington"]

... но больше ничего

[1600, "Pennsylvania", "Avenue", "NW", 20500]

 

Содержит (Contains)

В то время как "items" схема должна быть действительной для каждого элемента в массиве, схема "contains" должна проверяться только по одному или нескольким элементам в массиве.

{
   "type": "array",
   "contains": {
     "type": "number"
   }
}

Одного "числа" достаточно, чтобы пройти этот проход:

["life", "universe", "everything", 42]

Но если у нас нет числа, это не сработает:

["life", "universe", "everything", "forty-two"]

Все цифры, конечно, тоже в порядке:

[1, 2, 3, 4, 5]

 

minContains / maxContains

minContains и maxContains можно использовать с contains, чтобы дополнительно указать, сколько раз схема соответствует ограничению contains. Эти ключевые слова могут быть любым неотрицательным числом, включая ноль.

{
  "type": "array",
  "contains": {
    "type": "number"
  },
  "minContains": 2,
  "maxContains": 3
}

Не проходит проверку minContains

["apple", "orange", 2]
["apple", "orange", 2, 4]
["apple", "orange", 2, 4, 8]

Не проходит проверку maxContains

["apple", "orange", 2, 4, 8, 16]

 

Длина

Длину массива можно указать с помощью ключевых слов minItems и maxItems. Значение каждого ключевого слова должно быть неотрицательным числом. Эти ключевые слова работают независимо от того, выполняется ли проверка списка или проверка кортежа.

{
  "type": "array",
  "minItems": 2,
  "maxItems": 3
}
[]
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]

 

Уникальность

Схема может гарантировать, что каждый из элементов массива уникален. Просто установите для ключевого слова uniqueItems  значение true.

{
  "type": "array",
  "uniqueItems": true
}
[1, 2, 3, 4, 5]
[1, 2, 3, 3, 4]

Пустой массив всегда проходит:

[]

 

Булево

Логический тип соответствует только двум специальным значениям: true и false. Обратите внимание, что значения, которые оцениваются как true или false, такие как 1 и 0, не принимаются схемой.

{ "type": "boolean" }
true
false
"true"

Значения, которые оцениваются как true или false, все еще не принимаются схемой:

0

 

Null

Когда схема задает тип null, она имеет только одно допустимое значение: null.

Примечание: Важно помнить, что в JSON значение null не эквивалентно отсутствию чего-либо. Пример см. в разделе Обязательные свойства.

{ "type": "null" }
null
false
0
""
 

 

Вторая часть //infostart.ru/1c/articles/1546672/

---

Благодарю за внимание.

 

См. также

SALE! 20%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)

Правила в универсальном формате обмена для ERP 2.5, КА 2.5, УТ 11.5, БП 3.0, Розница, УНФ, для последних версий конфигураций. Ссылки на другие конфигурации в описании публикации. Правила совместимы со всеми другими версиями конфигураций новыми и старыми, поддерживающими обмен и синхронизацию в формате EnterpriseData. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой.

26280 22338 руб.

12.06.2017    141628    799    297    

419

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УПП 1.3 (1.3.236.x) и БП 3.0 (3.0.164.x). Правила подходят для версии ПРОФ и КОРП.

35000 31500 руб.

15.12.2021    24083    169    51    

128

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 10 Россия Управленческий учет Платные (руб)

Перенос данных из 1С:Управление торговлей 10.3 в 1С:Управление торговлей 11.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УТ 10.3 (10.3.88.x) и УТ 11.5 (11.5.19.x).

35000 31500 руб.

23.07.2020    51363    228    70    

186

SALE! 15%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 Платформа 1C v8.2 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Управление производственным предприятием Россия Платные (руб)

Регулярный обмен, выгрузка, перенос из КА 1.1, УПП 1.3, УТ 10.3 для обмена с любыми конфигурациями, поддерживающими обмен в формате EnterpriseData (КД3) - БП 3.0, ERP, КА 2, УТ 11, Розница 2, УНФ 1.6 и другими. Правила для старых и доработанных конфигураций не требуют синхронного обновления и совместимы с новыми и будущими конфигурациями. Обмен по расписанию, через папку, FTP, почту.

15300 13005 руб.

18.02.2016    186927    590    509    

526

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Перенос данных из ERP в БП 3 | из КА 2 в БП 3 | из УТ 11 в БП 3 | из ЕРП в БП 3 | Сэкономьте время - используйте готовое решение для перехода! | Перенос разработан в формате КД 2 (правила конвертации данных) | Переносятся все возможные виды документов, начальных остатков и нормативно-справочная информация| Можно опционально выгружать каждую пару "номенклатура+характеристика" как отдельную номенклатуру | Есть выгрузка настроек счетов учета и зарплатных данных из ERP / КА 2 | Можно проверить на вашем сервере перед покупкой

55778 50200 руб.

15.04.2019    72127    181    150    

123

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 Сложные периодические расчеты 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Платные (руб)

Правила переноса кадровых и расчетных данных и справочной информации из "1С:УПП1.3" или "1С:КА 1.1" в "1С:ЗУП 3.1 | Разработан в формате КД 2 (правила конвертации данных) | При выгрузке есть фильтр по организациям | Обновляется при выходе новых релизов 1С | Развитие алгоритмов | Расчетные документы переносятся в документ "Перенос данных" | Создаются документы "Начальная штатная расстановка" и "Начальная задолженность по зарплате", переносятся кадровые документы

55778 50200 руб.

29.10.2018    56234    59    105    

61

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена | Можно выполнить переход с УПП на БП 3 или запускать выгрузку данных за выбранный период времени | Переносятся документы, начальные остатки и вся справочная информация | Есть фильтр по организации и множество других параметров выгрузки | Поддерживается несколько сценариев работы: как первичный полный перенос, так и перенос только новых документов | Перенос данных возможен в "1С: Бухгалтерия 3.0" версии ПРОФ, КОРП или базовую | Переход с "1С: УПП1.3" / "1С:КА 1.1" на "1С:БП3.0" с помощью правил конвертации будет максимально комфортным! | Можно бесплатно проверить перенос на вашем сервере!

48278 43450 руб.

25.02.2015    171212    303    257    

378

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из ERP в ЗУП 3 | из КА 2 в ЗУП | Готовые правила конвертации данных (КД 2) для переноса остатков, документов с движениями и справочной информации 3 | Есть перенос начальной задолженности по зарплате и начальной штатной расстановки на выбранную дату | Обороты за прошлые годы (данные для расчета среднего) переносятся свернуто в документ "Перенос данных" | Есть фильтр по организациям | Документы за текущий период переносятся сразу с движениями, поэтому не потребуется делать перерасчеты | Перенос можно проверить перед покупкой, обращайтесь!

53111 47800 руб.

03.12.2020    36632    94    66    

90
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. kotlovD 88 08.11.21 07:05 Сейчас в теме
Спасибо, очень полезно, жду следующих публикаций
2. tormozit 7233 10.11.21 07:26 Сейчас в теме
Во встроенном языке 1С к сожалению пока нет объекта для работы со схемой JSON.
Про редакторы схем (визуальные средства создания) в этой статье было бы полезно упомянуть. Например есть бесплатный онлайн редактор https://jsonschema.net
potoyalo; +1 Ответить
Оставьте свое сообщение