JSON Schema away to specify an "any"-type schema with certain required fields

19,344

[disclaimer: author of the next JSON Schema validation spec here]

OK, it is unclear what you ask, see below, but one of your examples clearly does not do what you want, this is the one where you write:

{ "type": [ "object", "any" ] }

This is equivalent to an empty schema, and as such validates each and every instance.

One way I read your question is that you want your JSON data to be either a tag array or an object with at least members named id, name and price. Since you seem to be using draft v3, you only have one solution:

{
    "type": [
        {
            "description": "schema for tags array here",
        },
        {
            "description": "schema for the base object here"
        }
    ]
}

This construct means that the instance must obey at least one schema inside type (and you can mix it with primitive types as well).

However: the current draft now being v4, you should now write:

{
    "anyOf": [
        {
            "description": "schema for tags array here",
        },
        {
            "description": "schema for the base object here"
        }
    ]
}

Note that not all implementations support draft v4, or the construct for type above. In fact, very few do. See below for a link to an online schema validator which supports both.

Another way that I read your question is that you want to allow properties other than id, name and price to be whatever they like. This is then quite simple. Just don't define a schema for tags in properties:

{
    "type": "object",
    "required": [ "id", "name", "price" ]
    "properties": {
        "id": {
            "type": "number"
        },
        "name": {
            "description": "Name of the product"
        },
        "price": {
            "type": "number",
            "minimum": 0
        }
    }
}

Since you don't specify additionalProperties as being false, the object instance can have any number of additional members, and these members can be anything.

Link to an online validator which can test your schemas: here

Share:
19,344

Related videos on Youtube

Bernardo Cunha
Author by

Bernardo Cunha

Updated on September 18, 2022

Comments

  • Bernardo Cunha
    Bernardo Cunha over 1 year

    Let's say I have the following JSON Schema

    {
     "name":"Product",
     "type":"object",
     "properties":{
       "id":{
         "type":"number",
         "required":true
       },
       "name":{
         "description":"Name of the product",
         "required":true
       },
       "price":{
         "required":true,
         "type": "number",
         "minimum":0,
         "required":true
       },
       "tags":{
         "type":"array",
         "items":{
           "type":"any"
         }
       }
     }
    }
    

    But, instead of tags being an array, I'd like it to be part of the root schema. So you could specify any property, but I give special attention to "id", "name" and "price" Which of the following would be the correct way of doing it, and which ones are completely wrong?

    {
     "name":"Product",
     "type":"object",
     "properties":{
       "id":{
         "type":"number",
         "required":true
       },
       "name":{
         "description":"Name of the product",
         "required":true
       },
       "price":{
         "required":true,
         "type": "number",
         "minimum":0,
         "required":true
       }
     },
     "additionalProperties": {
         "type":"any"
     }
    }
    
    {
     "name":"Product",
     "type":"object",
     "properties":{
       "id":{
         "type":"number",
         "required":true
       },
       "name":{
         "description":"Name of the product",
         "required":true
       },
       "price":{
         "required":true,
         "type": "number",
         "minimum":0,
         "required":true
       }
     },
     "extends": {
         "type":"any"
     }
    }
    
    {
     "name":"Product",
     "type":["object","any"],
     "properties":{
       "id":{
         "type":"number",
         "required":true
       },
       "name":{
         "description":"Name of the product",
         "required":true
       },
       "price":{
         "required":true,
         "type": "number",
         "minimum":0,
         "required":true
       }
     }
    }
    

    I can come up with a few more (such as inverting roles of "any" and "object"), but they are all derivative of these three examples.

  • Turnsole
    Turnsole about 11 years
    This was very helpful, I didn't realize that you could define multiple possible type values. (Yeah, newb at json schemas here.)
  • fge
    fge about 11 years
    And, errr, what do you want to do, then? You still did not really tell ;)
  • Turnsole
    Turnsole about 11 years
    I didn't really say anything, it wasn't my question. I just happened to show up thanks to Google. If you're curious, though, I was trying to handle the case when the API I'm getting JSON from sends me an object some of the time and an integer other times, but I still want one of those two and not "any".
  • fge
    fge about 11 years
    You can post a message to the JSON Schema google group, they'll help you make your schema ;)
  • Bernardo Cunha
    Bernardo Cunha about 11 years
    Sorry being late on this, but you have answered my question and then some. Brilliant. Thanks a ton. :)
  • amey91
    amey91 about 9 years
    @fge what if my schema element can either be an array or null? If I try writing null, it gives me an error: "found null, expected one of [array, string]"
  • fge
    fge about 9 years
    @amey91 a null value in JSON Schema is "type": "null", or, if in an enum, the value null: { "enum": [ null ] }
  • amey91
    amey91 about 9 years
    @fge TY! I was using null without quotation marks and that was causing the error