Re: [json-schema] How do I make a few properties of an object mutually exclusive?

2,757 views
Skip to first unread message

Francis Galiegue

unread,
Mar 20, 2013, 1:10:54 PM3/20/13
to json-...@googlegroups.com
On Wed, Mar 20, 2013 at 5:39 PM, <apoth...@gmail.com> wrote:
> I here is are examples of the types of JSON I'm trying to validate:
>
> VALID:
> <code language="json>
> {
> "mutexA": {}
> "anotherProperty": {}
> }
> </code>
>
> VALID:
> <code language="json>
> {
> "mutexB": {}
> "anotherProperty": {}
> }
> </code>
>
> INVALID:
> <code language="json>
> {
> "mutexA": {},
> "mutexB": {}
> "anotherProperty": {}
> }
> </code>
>
> How would I go about making a JSON schema that correctly validates for this
> mutually exclusive behavior?
>

Use a combination of "required" and "additionalProperties", ie:

{
"type": "object",
"required": [ "mutexA", "anotherProperty" ],
"additionalProperties": false
}

then define schemas for "mutexA" and "anotherProperty" in "properties".

--
Francis Galiegue, fgal...@gmail.com
JSON Schema in Java: http://json-schema-validator.herokuapp.com

chris...@grierwhite.com

unread,
Nov 5, 2013, 2:05:28 PM11/5/13
to json-...@googlegroups.com
Hi Michael,

I just ran into the use case as well and discovered a rather elegant solution using 'not' and 'required'.  This avoids duplicating the definitions of the properties and is also scalable to mutual exclusivity with regard to multiple pairs of properties.

The following schema has these conditions:
  • 5 defined propertes: a1, a2, b, c1, c2
  • b is always required
  • a1 and a2 are mutually exclusive, either a1 or a2 must be present
  • c1 and c2 cannot both be specified, but they can both be omitted
{
  "type": "object",
  "properties": {
    "a1": { "type": "number" },
    "a2": { "type": "number" },
    "b": { "type": "string" },
    "c1": { "type": "string" },
    "c2": { "type": "string" }
  },
  "additionalProperties": false,
  "required": [ "b" ],
  "allOf": [
    {
      "not": {
        "type": "object",
        "required": [ "a1", "a2" ]
      }
    },
    {
      "oneOf": [
        {
          "type": "object",
          "required": [ "a1" ]
        },
        {
          "type": "object",
          "required": [ "a2" ]
        }
      ]
    },
    {
      "not": {
        "type": "object",
        "required": [ "c1", "c2" ]
      }
    }
  ]

Geraint

unread,
Nov 5, 2013, 6:59:38 PM11/5/13
to json-...@googlegroups.com
@Christopher: for the a1/a2 pair, you actually don't need "not" at all.

A "oneOf" condition will fail if more than one condition is met.  So this part on its own:
    {
      "oneOf": [
        {
          "type": "object", 
          "required": [ "a1" ]
        }, 
        {
          "type": "object", 
          "required": [ "a2" ]
        }
      ]
    }
fully handles the a1/a2 constraints.  Data with either "a1" or "a2" is valid, but data with both is invalid, because it matches more than one condition in "oneOf".

However, your use of "not" for the c1/c2 condition is good (although not the only solution). :)
Reply all
Reply to author
Forward
0 new messages