问题
I have six properties: name, age, phone, deletePhone, address, deleteAddress.
I want to create schema that allows anyOf above properties but phone should not be present with deletePhone and address should not be present with deleteAddress(and vice versa).
I have tried this schema:
{
"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"]
}
]
}
]
}
It validates true
{
"name": "my name",
"address": "some addr",
"phone": 34
}
and validates false for
{
"address": "some addr",
"phone": 34,
"deletePhone": true
}
which is correct but it also validates false for
{
"phone": 34
}
or
{
"name": "some name"
}
Which i want to validate true, i know i'm missing some combination of anyOf, oneOf, Or is there any better way?
回答1:
I think this is the simplest solution.
{
"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"] } }
]
}
回答2:
EDIT: A different but more reliable and compact approach.
{
"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"]}}
]
}
]
}
]
}
Tested with ajv
: https://runkit.com/embed/5qwkquyweir2
OLD (not working):
If you can allow null
value to be equal to property not present, the schema could be that simple:
{
"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"]
},
{}
]
}
]
}
But if you can not allow {"deletePhone":null,"phone":123}
schema is more complicated and repeated:
{
"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
},
{}
]
}
]
}
回答3:
Below schema works with all cases but it is lengthy.
{
"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
}
]
}
来源:https://stackoverflow.com/questions/50968780/how-to-allow-one-property-only-if-other-is-not-present-and-allow-any-of-other-pr