如何仅在不存在其他属性的情况下允许一个属性,并在json模式中允许其他属性

时间:2018-06-21 12:37:52

标签: json jsonschema

我有六个属性:姓名,年龄,电话,deletePhone,地址,deleteAddress。

我想创建允许上述任何属性的架构,但phone不应与deletePhone一起出现,而地址不应与deleteAddress一起出现(反之亦然)。

我尝试过以下模式:

{
    "type": "object",
    "properties": {
      "name": {
        "type": "string"
      },
      "age": {
        "type": "number"
      },
      "phone": {
        "type": "number"
      },
      "deletePhone": {
        "type": "boolean"
      },
      "address": {
        "type": "string"
      },
      "deleteAddress": {
        "type": "boolean"
      }
    },
    "allOf": [
      {
        "oneOf": [
          {
            "required": ["phone"]
          },
          {
            "required": ["deletePhone"]
          }
        ]
      },
      {
        "oneOf": [
          {
            "required": ["address"]
          },
          {
            "required": ["deleteAddress"]
          }
        ]
      }
    ]
}

它证实为真

{
    "name": "my name",
    "address": "some addr",
    "phone": 34
}

并验证

为假
{
    "address": "some addr",
    "phone": 34,
    "deletePhone": true
}

这是正确的,但它也验证了错误的

{
    "phone": 34
}
or
{
    "name": "some name"
}

我想验证真,我知道我缺少anyOf,oneOf的某种组合,还是有更好的方法?

3 个答案:

答案 0 :(得分:2)

我认为这是最简单的解决方案。

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "number" },
    "phone": { "type": "number" },
    "deletePhone": { "type": "boolean" },
    "address": { "type": "string" },
    "deleteAddress": { "type": "boolean" }
  },
  "allOf": [
    { "not": { "required": ["phone", "deletePhone"] } },
    { "not": { "required": ["address", "deleteAddress"] } }
  ]
}

答案 1 :(得分:1)

编辑:一种不同但更可靠,更紧凑的方法。

{
  "type": "object",
  "properties": {
    "name": {"type": "string"},
    "age": {"type": "number"},
    "phone": {"type": "number"},
    "deletePhone": {"type": "boolean"},
    "address": {"type": "string"},
    "deleteAddress": {"type": "boolean"}
  },
  "additionalProperties": false,
  "allOf": [
    {
      "oneOf": [
        {
          "allOf": [
            {"required": ["phone"]},
            {"not":{"required":["deletePhone"]}}
          ]
        },
        {
          "allOf": [
            {"required": ["deletePhone"]},
            {"not":{"required":["phone"]}}
          ]
        },
        {
          "allOf": [
            {"not":{"required": ["deletePhone"]}},
            {"not":{"required":["phone"]}}
          ]
        }
      ]
    },
    {
      "oneOf": [
        {
          "allOf": [
            {"required": ["address"]},
            {"not":{"required":["deleteAddress"]}}
          ]
        },
        {
          "allOf": [
            {"required": ["deleteAddress"]},
            {"not":{"required":["address"]}}
          ]
        },
        {
          "allOf": [
            {"not":{"required": ["deleteAddress"]}},
            {"not":{"required":["address"]}}
          ]
        }
      ]
    }
  ]
}

经过ajv测试:https://runkit.com/embed/5qwkquyweir2


老(不起作用):

如果您可以允许null的值等于不存在的属性,则该架构可能就这么简单:

{
  "type": "object",
  "properties": {
    "name": {"type": "string"},
    "age": {"type": "number"}
  },
  "allOf": [
    {
      "oneOf": [
        {
          "properties": {
            "phone": {"type": "number"},
            "deletePhone": {"type": "null"}
          },
          "required": ["phone"]
        },
        {
          "properties": {
            "phone": {"type": "null"},
            "deletePhone": {"type": "boolean"}
          },
          "required": ["deletePhone"]
        },
        {}
      ]
    },
    {
      "oneOf": [
        {
          "properties": {
            "address": {"type": "string"},
            "deleteAddress": {"type": "null"}
          },
          "required": ["address"]
        },
        {
          "properties": {
            "address": {"type": "null"},
            "deleteAddress": {"type": "boolean"}
          },
          "required": ["deleteAddress"]
        },
        {}
      ]
    }
  ]
}

但是,如果您不允许{"deletePhone":null,"phone":123}模式,则更加复杂且重复:

{
  "type": "object",
  "properties": {
    "name": {"type": "string"},
    "age": {"type": "number"}
  },
  "allOf": [
    {
      "oneOf": [
        {
          "properties": {
            "name": {},
            "age": {},
            "address": {},
            "deleteAddress": {},
            "phone": {"type": "number"}
          },
          "required": ["phone"],
          "additionalProperties": false
        },
        {
          "properties": {
            "name": {},
            "age": {},
            "address": {},
            "deleteAddress": {},
            "deletePhone": {"type": "boolean"}
          },
          "required": ["deletePhone"],
          "additionalProperties": false
        },
        {}
      ]
    },
    {
      "oneOf": [
        {
          "properties": {
            "name": {},
            "age": {},
            "phone": {},
            "deletePhone": {},
            "address": {"type": "string"}
          },
          "required": ["address"],
          "additionalProperties": false
        },
        {
          "properties": {
            "name": {},
            "age": {},
            "phone": {},
            "deletePhone": {},
            "deleteAddress": {"type": "boolean"}
          },
          "required": ["deleteAddress"],
          "additionalProperties": false
        },
        {}
      ]
    }
  ]
}

答案 2 :(得分:0)

以下模式适用于所有情况,但很长。

{
  "type": "object",
    "oneOf": [
      {
        "anyOf": [
          {
            "oneOf": [
              {
                "properties": {
                  "phone": {
                    "type": "number"
                  },
                  "address": {
                    "type": "string"
                  },
                  "deleteAddress": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "phone"
                ],
                "not": {
                  "required": [
                    "deletePhone"
                  ]
                }
              },
              {
                "properties": {
                  "deletePhone": {
                    "type": "boolean"
                  },
                  "address": {
                    "type": "string"
                  },
                  "deleteAddress": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "deletePhone"
                ],
                "not": {
                  "required": [
                    "phone"
                  ]
                }
              },
              {
                "oneOf": [
                  {
                    "required": [
                      "phone",
                      "address",
                      "deleteAddress"
                    ]
                  },
                  {
                    "required": [
                      "deletePhone",
                      "address",
                      "deleteAddress"
                    ]
                  }
                ]
              }
            ]
          },
          {
            "oneOf": [
              {
                "properties": {
                  "address": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "number"
                  },
                  "deletePhone": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "address"
                ],
                "not": {
                  "required": [
                    "deleteAddress"
                  ]
                }
              },
              {
                "properties": {
                  "deleteAddress": {
                    "type": "boolean"
                  },
                  "phone": {
                    "type": "number"
                  },
                  "deletePhone": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "deleteAddress"
                ],
                "not": {
                  "required": [
                    "address"
                  ]
                }
              },
              {
                "oneOf": [
                  {
                    "required": [
                      "address",
                      "phone",
                      "deletePhone"
                    ]
                  },
                  {
                    "required": [
                      "deleteAddress",
                      "phone",
                      "deletePhone"
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "number"
          }
        },
        "additionalProperties": false
      }
    ]
}