Сложный сценарий со схемой JSON if-else condition

#json #jsonschema

#json #jsonschema

Вопрос:

     {
        "policyHolder": {
            "fullName": "A"
        },
        "traveller": [
            {
                "fullName": "B",
                "relationship": "Spouse"
            },
            {
                "fullName": "A",
                "relationship": "My Self"
            }
        ]
    }
  

В приведенном выше json я хочу подтвердить, что

  • if "relationship" = "My Self" затем fullName должно соответствовать fullName в policyHolder
  • Поле relationship должно существовать в traveller массиве, иначе json недопустим

Я пытался создать схему json с помощью if-else , allOf и т.д. Но ничего не работает, что могло бы выполнить эти проверки, но не смогло. Пожалуйста, помогите!!

Схема:

 {
    "type": "object",
    "required": [
        "policyHolder",
        "traveller",
    ],
    "properties": {
        "policyHolder": {
            "$id": "#/properties/policyHolder",
            "type": "object",
            "required": [
                "fullName"
            ],
            "properties": {
                "fullName": {
                    "$id": "#/properties/policyHolder/properties/fullName",
                    "type": "string",
                }
            }
        },
        "traveller": {
            "$id": "#/properties/traveller",
            "type": "array",
            "minItems": 1,
            "items": {
                "$id": "#/properties/traveller/items",
                "type": "object",
                "properties": {
                    "fullName": {
                        "$ref": "#/properties/policyHolder/properties/fullName"
                    },
                    "relationship": {
                        "$id": "#/properties/traveller/items/properties/relationship",
                        "type": "string",
                    }
                },
                "required": [
                    "fullName",
                    "relationship"
                ],
                }
            }
        }
    }```

  

Ответ №1:

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

Во-вторых, я бы посоветовал вам извлечь некоторые из ваших подсхем в определения, а не пытаться возиться с идентификаторами. Идентификаторы обычно более полезны, если вы ссылаетесь на них из других документов или используете короткие (например, из одного слова) идентификаторы. Определение идентификатора в качестве его местоположения в документе является избыточным; большинство процессоров обработают это автоматически.

 {
  "type": "object",
  "required": [
    "policyHolder",
    "traveller",
  ],
  "definitions": {
    "person": {
      "type": "object"
      "properties": {
        "fullName": {"type": "string"}
      },
      "required": ["fullName"]
    },
    "relationship": { "enum": [ ... ] }   // list possible relationships
  },
  "properties": {
    "policyHolder": { "$ref": "#/definitions/person" },
    "traveller": {
      "type": "array",
      "minItems": 1,
      "items": {
        "allOf": [
          { "$ref": "#/definitions/person" },
          {
            "properties": {
              "relationship": { "$ref": "#/definitions/relationship" }
            },
            "required": ["relationship"]
          }
        ]
      }
    }
  }
}
  

(Я извлек relationship в его собственное определение enum, но это действительно необязательно. Вы можете оставить его встроенным или даже неограниченной строкой, если у вас нет определенного набора связей.)

Ответ №2:

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

Вот как бы вы решили свою проблему с $data .

 {
  "type": "object",
  "properties": {
    "policyHolder": {
      "type": "object",
      "properties": {
        "fullName": { "type": "string" }
      }
    },
    "traveler": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "fullName": { "type": "string" },
          "relationship": { "type": "string" }
        },
        "if": {
          "properties": {
            "relationship": { "const": "My Self" }
          }
        },
        "then": {
          "properties": {
            "fullName": { "const": { "$data": "#/policyHolder/fullName" } }
          }
        }
      }
    }
  }
}
  

Без $data вам придется выполнить эту проверку в коде или изменить структуру данных, чтобы в этом не было необходимости.