Как представить типы объединения в JSON валидаторе схемы? - PullRequest
0 голосов
/ 15 апреля 2020

Я новичок в JSON проверке схемы и создаю собственную схему для конфигурации. Схема, которую я строю, основана на типе Typescript. Я понимаю, как я могу проверить простые типы данных, такие как массив, объект, число, строка и т. Д. c.

Но есть ли способ указать типы, подобные этому:

type Conf = {
idle_session_timeout?: number | "none",
item: {
    kind: "attribute";
    name: string;
} | {
    kind: "relation";
    name: string;
} | {
    kind: "group";
    name: string;
    label?: string | undefined;
    entries: PresentationItem[];
}
 order_by: string | {
    attribute: string;
    direction?: "asc" | "desc" | undefined;
}
}

Я заметил из http://json-schema.org/draft-07/schema, что он поддерживает операторы if then else для переключения на основе схемы валидации по стоимости, но я не знаю, как их реализовать.

1 Ответ

1 голос
/ 15 апреля 2020

Есть несколько ключевых слов, на которые вы хотите обратить внимание и, вероятно, обратитесь к спецификации для:

Во-первых, «тип» позволяет указывать несколько значений в массиве. При этом вы можете указать, например, ["string", "number"], что означает «строка или число». Многие ключевые слова применяются, только когда экземпляр имеет определенный тип JSON. Как правило, вы можете комбинировать схему одного «типа» и другой с другим «типом», если все остальные ключевые слова применяются только к соответствующим типам.

Так, например, вы можете иметь два схемы типа:

{
  "type": "string",
  "minLength": 1
}
{
  "type": "number",
  "minimum": 0
}

И поскольку «минимум» применяется только к числам, а «minLength» применяется только к строкам, вы можете просто объединить схемы вместе, и это будет иметь тот же эффект:

{
  "type": ["string", "number"],
  "minLength": 1
  "minimum": 0
}

Однако, с двумя схемами одного и того же "типа", выполнение этого будет выполнять пересечение вместо объединения. Это связано с тем, что при добавлении ключевых слов в схему JSON добавляются ограничения, а при добавлении значений в список «type» удаляются ограничения (больше значений становятся действительными).

Поэтому, если вы выполняете объединение двух схем одного и того же типа или, если вы комбинируете схемы с ключевыми словами, которые проверяются для всех типов (в частности, enum или const), вам необходимо объединить их с ключевым словом anyOf, которое выполняет объединение в массиве нескольких схем. (Вы также можете рассмотреть вариант «oneOf».)


Я думаю, что у вас получится такая схема:

{
"type": "object",
"properties": {
  "idle_session_timeout": {
    "type": ["number","string"],
    "anyOf": [ {"type":"number"}, {"const":"none"} ]
  },
  "item": {
    "type": "object",
    "required": ["kind", "name"],
    "properties": {
      "kind": { "type": "string" },
      "name": { "type": "string" },
    },
    "anyOf": [
      {
        "properties": {
          "kind": { "const": "attribute" },
        }
      },
      {
        "properties": {
          "kind": { "const": "relation" },
        }
      },
      {
        "required": ["entries"],
        "properties": {
          "kind": { "const": "group" },
          "label": { "type": "string" },
          "entries": { "type":"array", "items": {"$ref":"PresentationItem"} },
        }
      }
    ]
  },
  "order_by": {
    "type": ["string", "object"],
    "required": ["attribute"],
    "properties": {
      "attribute": { "type": "string" },
      "direction": { "enum": ["asc", "desc"] },
    }
  }
}

Обратите внимание на то, как я выделил общие ключевые слова из «anyOf» в максимально возможный уровень. Это стилист c выбор. Это приводит к чуть более чистым ошибкам, но может не иметь значения для вас, в зависимости от того, как вы планируете расширять схему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...