How to make anyOf a set of multipurpose properties except one

I have an outdated API that I am trying to define in a JSON schema, and the object has a strange structure where there is a set of 4 properties, any of them are necessary, and 3 of them are mutually exclusive. After that there are more than 30 common additional properties, I will mark them as ...

eg.

 { "foo": "bar", "baz": 1234, ... } // OK { "foo": "bar", "buzz": 1234, ... } // OK { "foo": "bar", "fizz": 1234, ... } // OK { "foo": 1234, ... } // OK { "baz": 1234, ... } // OK { ... } // NOT OK { "baz": 1234, "buzz": 1234, ... } // NOT OK 

I could make oneOf , but not allowing foo be present along with others, anyOf allows baz , buzz and fizz to be present with each other, it is impossible.

I tried to define something like the following:

 { "type": "object", "properties": { "foo": {"type": "string"}, "baz": {"type": "number"}, "buzz": {"type": "number"}, "fizz": {"type": "number"} }, "anyOf": [ {"required": ["foo"]}, {"required": [{"oneOf": [ {"required": ["baz"]}, {"required": ["buzz"]}, {"required": ["fizz"]} ]} ]} ] } 

and

 { "type": "object", "properties": { "foo": {"type": "string"}, "baz": {"type": "number"}, "buzz": {"type": "number"}, "fizz": {"type": "number"} }, "anyOf": [ {"required": ["foo"]}, {"oneOf": [ {"required": ["baz"]}, {"required": ["buzz"]}, {"required": ["fizz"]} ] } ] } 

But this does not work, and I just don’t know enough about the json scheme, but I know if this is possible.

+6
source share
2 answers

Interesting! There may be a more accurate solution, but here we go ...

a “mutually exclusive” restriction can be expressed by prohibiting pairwise combinations of properties:

 { "not": { "anyOf": [ {"required": ["baz", "buzz"]}, {"required": ["buzz", "fizz"]}, {"required": ["fizz", "baz"]} ] } } 

"At least one of the" constraints can be expressed using anyOf :

 { "anyOf": [ {"required": ["foo"]}, {"required": ["baz"]}, {"required": ["buzz"]}, {"required": ["fizz"]} } } 

If you simply combine these two constraints into one scheme, then it should work:

 { "not": {"anyOf": [...]}, "anyOf": ... } 
+11
source

You can make the properties mutually exclusive in the JSON scheme using pairwise exceptions, but this leads to a combinatorial explosion. This becomes a problem when you have many mutually exclusive properties.

The linear solution has the form:

  • one of:
    • property a
    • property b
    • property c
    • none of:
      • property a
      • property b
      • property c

It only pays off if you have many properties.

 { "oneOf": [ { "required": ["baz"] }, { "required": ["buzz"] }, { "required": ["fizz"] }, { "not": { "anyOf": [ { "required": ["baz"] }, { "required": ["buzz"] }, { "required": ["fizz"] } ] } } ] } 

Combine this with @cloudfeet's answer to get the answer to your specific question.

+2
source

Source: https://habr.com/ru/post/971105/


All Articles