如何让一个属性只有在其他不存在,并且允许JSON模式中的任何其他化子性质的(How to allow

2019-09-29 09:02发布

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

我想创建的架构,允许anyOf上述特性,但手机不应该存在与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的某种组合,或者是还有什么更好的办法?

Answer 1:

我觉得这是最简单的解决方案。

{
  "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"] } }
  ]
}


Answer 2:

编辑:一个更可靠的和紧凑的方法。

{
  "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


OLD(不工作):

如果你能允许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
        },
        {}
      ]
    }
  ]
}


Answer 3:

下面的模式适用于所有的情况下,却是漫长的。

{
  "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
      }
    ]
}


文章来源: How to allow one property only if other is not present and allow any of other propeties in json schema