Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON Schema - multiple types

I have this schema. It checks comments, and works fine at the moment.

var schema = {
  id: '',
  type: 'object',
  additionalProperties: false,
  properties: {
    text: {
      type: 'string',
      minLength: 1,
      required: true
    },
    author: {
      type: 'number',
      required: true
    }
  }
}; 

My comment structure is:

{
  text: "Hello world!",
  author: 1
}

But now, I need to validate an array of objects like this. So I can get something like:

  [
    {
      text: "Hello world! Im comment #1",
      author: 1
    },
    {
      text: "Super awesome comment #2!",
      author: 0
    }
  ]

Sometimes I get one comment only so I get one object, and need to use first schema, but sometimes I get an array of comments, and my schema does not fit.

I heard about json schema anyOf, but I dont know how to do it.

Some like:

anyOf  
   schema-1 (object)
   schema-2 (array with objects)

Any help?

Thanks.

like image 237
Baumannzone Avatar asked Oct 06 '15 09:10

Baumannzone


People also ask

What is type in JSON Schema?

The type keyword is fundamental to JSON Schema. It specifies the data type for a schema. At its core, JSON Schema defines the following basic types: string. number.

What does $Ref mean in JSON Schema?

In a JSON schema, a $ref keyword is a JSON Pointer to a schema, or a type or property in a schema. A JSON pointer takes the form of A # B in which: A is the relative path from the current schema to a target schema. If A is empty, the reference is to a type or property in the same schema, an in-schema reference.

How do you reference a JSON Schema in another JSON Schema?

A schema can reference another schema using the $ref keyword. The value of $ref is a URI-reference that is resolved against the schema's Base URI. When evaluating a $ref , an implementation uses the resolved identifier to retrieve the referenced schema and applies that schema to the instance.

What is $id in JSON Schema?

$id is a reserved keyword. It serves for: Declaring an identifier for the schema or subschema. Declaring a base URL against which $ref URLs are resolved.


1 Answers

The solution is to have a common definition in one place, and then reference that common definition from two different options inside oneOf:

Here, we put the simple object definition inside definitions:

{
    "definitions": {
        "singleObject": {
            ... same definition as in your question ...
        }
    }
}

We then reference this schema, inside oneOf:

{
    "oneOf": [
        {"$ref": "#/definitions/singleObject"}, // plain object
        {
            "type": "array", // array of plain objects
            "items": {"$ref": "#/definitions/singleObject"}
        }
    ],
    "definitions": {
        "singleObject": {...}
    }
}

You can organise this a few different ways - I personally often end up with the simple-object definition as the root schema, and have the single/array switcher in definitions, so the schema for my documents is actually http://example.com/schema#/definitions/arrayOrSingle.

like image 182
cloudfeet Avatar answered Nov 13 '22 08:11

cloudfeet