Убедитесь, что свойство элемента в массиве уникально в схеме Json?

Учитывая следующую схему JSON, можно ли указать, что свойство "имя" должно быть уникальным (т.е. в массиве "элементы" НЕ должно быть двух элементов с одинаковым "именем".

{
  "root": {
    "type": "object",
    "properties": {
      "elements": {
        "type": "array",
        "minItems": 1,
        "items": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "title": "Element Name",
              "minLength": 3,
            },
            "url": {
              "type": "string",
              "title": "Some URL"
            }
          }
        }
      }
    }
  }
}

Я пытался использовать ключевое слово uniqueItems, но, похоже, оно было разработано для простых списков значений.

Ответ 1

Нет, это невозможно. Из документации json-schema:... формат JSON для определения структуры данных JSON.

Это довольно ограниченно для проверки достоверности данных, поскольку это не является целью стандарта. Многие люди спрашивали об этом раньше, потому что обычно запрашивается своего рода "уникальный идентификатор". К сожалению для тех, кому это нужно, json-schema не предоставляет вам этого.

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

Ответ 2

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

  • Заменить массив на карту. Этого можно легко достичь, используя объект с patternProperties. Шаблон является регулярным выражением. Любой объект, соответствующий шаблону, будет проверен на соответствие шаблону свойства pattern. Образец, соответствующий любой строке >= 3 символа, выглядит следующим образом: "....*", но кажется, что всегда имеет значение trailing ".*", поэтому "..." работает.
  • Добавление дополнительных свойств: false - дополнительный шаг для принудительного применения вашего ограничения (minLength:3).
  • Чтобы обеспечить по крайней мере один элемент на вашей карте (вы использовали minItems:1 для своего массива), замените minItems на minProperties.

... приводит к следующей схеме:

"root": {
  "type": "object", 
  "properties": {
    "elements": {
      "type": "object", 
      "patternProperties": {
        "...": {
          "type": "object", 
          "properties": {
            "url": {
              "type": "string"
            }
          }
        }
      }, 
      "additionalProperties": false, 
      "minProperties": 1
    }
  }
}

Если документ, подобный следующему (выдержка), соответствует вашей старой схеме,

"elements": [
  {
    "name": "abc", 
    "url": "http://myurl1"
  }, 
  {
    "name": "def", 
    "url": "http://myurl2"
  }, 
  {
    "name": "ghij", 
    "url": "http://myurlx"
  }
]

... такой документ (выдержка) будет соответствовать новой схеме:

"elements": {
  "abc": {
    "url": "http://myurl1"
  }, 
  "def": {
    "url": "http://myurl2"
  }, 
  "ghij": {
    "url": "http://myurlx"
  }
}

Ответ 3

Если ваш сценарий использования может справиться с дополнительными издержками, вы можете применить преобразование к документу для создания сокращенного документа, а затем снова применить проверку с отдельной мини-схемой к сокращенному документу.

Вот несколько ссылок с информацией об инструментах преобразования Json:

Обработка вашего примера будет очень простой в JSONata.