Сопоставление схемы Json с ‘anyOf’

#json #jsonschema

#json #jsonschema

Вопрос:

Я хотел бы иметь возможность управлять массивом «объектов» в формате json, где каждый объект имеет тип и свойства, и возникает ошибка схемы, если в объекте отсутствует обязательное свойство.

Это моя попытка сделать это (не включая часть массива), объявляя два типа объектов и говоря, что объект в json может быть любого из этих типов:

 {
  'definitions': 
  {
    'typeone': 
    {
      'type': 'object',
      'properties': 
      {
        'xtype': {'type':'string', 'const':'typeone'},
        'num' :  {'type':'number'}
      },
      'required':['xtype', 'num'],
      'additionalProperties':false
    },
    'typetwo': 
    {
      'type': 'object',
      'properties': 
      {
        'xtype': {'type':'string', 'const':'typetwo'},
        'str' :  {'type':'string'}
      },
      'required':['xtype', 'str'],
      'additionalProperties':false
    }
  },
  'anyOf':
  [
     { '$ref': '#/definitions/typeone' },
     { '$ref': '#/definitions/typetwo' },
  ]
}
  

Однако, если я передам ему json, который завершится неудачей, потому что в таком объекте отсутствует обязательное свойство:

 {
  'xtype': 'typeone'
}
  

… это ошибка с JSON does not match any schemas from 'anyOf'. — я вижу, причина в том, что он не знает, чтобы попытаться сопоставить xtype, вместо этого он просто считает xtype ‘typeone’ недействительным и смотрит на других.

Есть ли лучший способ сделать anyOf это, который будет жестко соответствовать на основе одного значения свойства (например, ‘switch’), а затем выдавать ошибки об отсутствии других обязательных свойств для этого типа объекта?

Комментарии:

1. Нет, но есть стандартизированный вывод из проекта схемы JSON 2019-09, который затем можно использовать для создания сообщений об ошибках. Извините.

Ответ №1:

Это становится намного более подробным, но вы можете использовать if / then для переключения проверки на основе свойства «xtype».

 {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "allOf": [
    {
      "if": {
        "type": "object",
        "properties": {
          "xtype": { "const": "typeone" }
        },
        "required": ["xtype"]
      },
      "then": { "$ref": "#/definitions/typeone" }
    },
    {
      "if": {
        "type": "object",
        "properties": {
          "xtype": { "const": "typetwo" }
        },
        "required": ["xtype"]
      },
      "then": { "$ref": "#/definitions/typetwo" }
    }
  ],
  "definitions": {
    "typeone": {
      "type": "object",
      "properties": {
        "xtype": {},
        "num": { "type": "number" }
      },
      "required": ["num"],
      "additionalProperties": false
    },
    "typetwo": {
      "type": "object",
      "properties": {
        "xtype": {},
        "str": { "type": "string" }
      },
      "required": ["str"],
      "additionalProperties": false
    }
  }
}
  

С небольшим изменением модели вы могли dependencies бы получить гораздо более простую и чистую схему. Вместо свойства «xtytpe» у вас может быть свойство, соответствующее имени типа. Например, { "typeone": true } .

 {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "dependencies": {
    "typeone": {
      "type": "object",
      "properties": {
        "typeone": {},
        "num": { "type": "number" }
      },
      "required": ["num"],
      "additionalProperties": false
    },
    "typetwo": {
      "type": "object",
      "properties": {
        "typetwo": {},
        "str": { "type": "string" }
      },
      "required": ["str"],
      "additionalProperties": false
    }
  }
}
  

Комментарии:

1. Спасибо за эту идею, о которой я не думал