JSON Schema Proposal

Abstract

JSON Schema is a specification for a JSON-based format for defining the structure of JSON data. JSON Schema provides a contract for what JSON data is required for a given application and how it can be modified, much like what XML Schema provides for XML. JSON Schema is intended to provide validation, documentation, and interaction control of JSON data. JSON Schema is based on the concepts from XML Schema, RelaxNG, and Kwalify, but is intended to be JSON-based, so that JSON data in the form of a schema can be used to validate JSON data, the same serialization/deserialization tools can be used for the schema and data, and it can be self descriptive.

Terminology

For this specification, a schema will be used to denote a JSON Schema definition, and an instance refers to the JSON object that the schema will be describing and validating. 

Schema Definition

A JSON Schema is a JSON Object that defines various attributes of the instance and defines it’s usage and valid values. A JSON Schema is a JSON Object with schema attribute properties. The following is the grammar of a JSON Schema:

 

schema = "{" *(<schema-attribute>,) "}"  ; a JSON Object with schema attribute properties
schema-attribute = (<schema attribute name> ":" <schema attribute value>) | ("type:" <type-definition>) | ("properties:" <object-type-definition>)

type-definition = union-type-definition | simple-type-definition
simple-type-definition = "string" | "number" | "integer" | "boolean" | "object" | "array" | "null" | "any"

union-type-definition = "[" 2+(<simple-type-definition>) "]"
object-type-definition = { *(property-definition,) }

property-definition = <the instance property name> ":" schema 


And an example JSON Schema definition could look like:

{"description":"A person",
 "type":"object",

 "properties":
  {"name": {"type":"string"},
   "age" : {"type":"integer",
     "maximum":125}}
}


A schema can have the following properties which are schema attributes (all attributes are optional):

Below is a more sophisticated example, first the instance object:

{
  "name" : "John Doe",
  "born" : "",
  "gender" : "male",
  "address" : 

   {"street":"123 S Main St",
    "city":"Springfield",
    "state":"CA"}
}

And here is a schema to validate it:

{"description":"A person",
 "type":"object",

 "properties": {
    "name": {"type":"string"},
    "born" : {"type":["integer","string"], allow for a numeric year, or a full date
          "minimum":1900, min/max for when a numberic value is used
          "maximum":2010,

          "format":"date-time", format when a string value is used
          "optional":true}
    ],
    "gender" : {"type":"string",
                "options":[

                   {"value:"male","label":"Guy"},

                   {"value":"female","label":"Gal"}]},
    "address" : {"type":"object"
,
                 "properties":{

                    "street":{"type":"string"},
                    "city":{"type":"string"},
                    "state":{"type":"string"}
                   }
                 }

  }
}

 

Extending and Referencing

Reusing existing JSON Schemas is strongly encouraged. JSON Schemas can be reused by using referencing and inheritance. It is recommended that an "id" property is used for identification and a "$ref" property is used to reference other objects as defined here: http://www.json.com/2007/10/19/json-referencing-proposal-and-library/ . Referencing by path is also allowed with this convention. This allows for circular references within schemas. Schemas from other domains may also be referencing using this convention, and it is recommended to utilize other common schemas whenever possible. There are a set of common schemas that can be found here. Extending a schema can be done by referring to the base schema with the "extends" property. If schema A has an "extends" property that refers to schema B, that means A extends the base schema, B, which requires that any value that is valid instance of schema A, MUST be a valid instance of schema B. An extended schema may redefine object properties, as long as the definition is the equally or more constraining the same property in the base schema. If the base schema has set additionalProperties to false, the extended schema may not define additional object properties. If the additionalProperties attribute is not defined, the extended schema may define additional object properties. If the additionalProperties attribute is defined, additional object properties must be at least as constraining as the definition in additionalProperties. For example, the following reference and extending may be made:

{
 "id":"person",
 "type":"object",
 "properties":{
   "name":{"type":"string"},
   "age":{"type":"integer"}
  }
}

Which can be extended:

{"id":"marriedperson",
 "extends":{"$ref":"person"},
 "properties":{
   "age":{"type":"integer",
             "minimum":17},
   "spouse":{"$ref":"marriedperson"}
  }
}

 

Here the second schema, marriedperson, inherits from the first schema, person. The marriedperson schema inherits the name property from person and redefines the age property to have a minimum value of 17 (which is more restrictive than the person\\47s definition). It also adds an additional property, spouse. The spouse is then defined to be have values that conform to the marriedperson schema. 

Self-Defined Schema Convention

JSON instance objects can also have a self defined object type definition. The recommended convention is that an instance object use a $schema property to refer to an object type definition which defines the type of the referring object. When defining a schema from an instance, the $schema property SHOULD be the first property (for linear parsers). Note that this is not limited to the root object, but any JSON object can refer to a schema to provide self-definition. For example:

{
  "$schema":
  {"properties":{
    "name": {"type":"string"},
    "age" : {"type":"integer",
      "maximum":125,
      "optional":true}
   }
  }
  "name" : "John Doe",
  "age" : 30,
  "type" : "object",

}

 

Note that self-defined object type definitions are optional, due to the possibility of name clashes.

Schema Definition Location Conventions

There are a couple of ways for schemas to be correlated with JSON data without actually including the schema in the object that are recommended. By using id referencing (per JSPON), ids provide an implicit URL through the web’s relative URL scheme. For example if an object is requested from http://mydomain.com/jsonData and returns:

{
"$schema":{"$ref":"mySchema"},

  "foo":"bar"
}

The reference to the schema here is an id reference, and using relative URL rules, it indicates to a client that a schema for this object can retrieved from http://mydomain.com/mySchema. We can also use an absolute URL reference:

{
"$schema":{"$ref":"http://mydomain.com/myObjectTypeDefinition"},

  "foo":"bar"}


Tools

An JavaScript implementation of a JSON Schema validator is available here.