Specification

Draft-06

Specification https://json-schema.org/draft-06/draft-wright-json-schema-01.html
Published21 April 2017
Authors
Austin Wright
Henry Andrews
Metaschemahttps://json-schema.org/draft-06/schema

Draft-06 release notes

Release notes for migrating from zyp-04 and fge-00 (draft-04) to wright-01 (draft-06).

NOTE: draft-07 has been released

Note that draft-07 core and validation are backwards-compatible with draft-06. For more information, see that draft's migration notes.

Q: What are the changes between draft-04 and draft-06?

Backwards-incompatible changes
keywordchangeconsequence
"id"replaced by "$id"no longer easily confused with instance properties named "id"
"$id"replaces "id"behavior is identical, $ prefix matches the other two core keywords
"$ref"only allowed where a schema is expectedit is now possible to describe instance properties named "$ref"
"exclusiveMinimum" and "exclusiveMaximum"changed from a boolean to a number to be consistent with the principle of keyword independencewherever one of these would be true before, change the value to the corresponding "minimum" or "maximum" value and remove the "minimum"/"maximum" keyword
"type"definition of "integer"in draft-04, "integer" is listed as a primitive type and defined as "a JSON number without a fraction or exponent part"; in draft-06, "integer" is not considered a primitive type and is only defined in the section for keyword "type" as "any number with a zero fractional part"; 1.0 is thus not a valid "integer" type in draft-04 and earlier, but is a valid "integer" type in draft-06 and later; note that both drafts say that integers SHOULD be encoded in JSON without fractional parts
Additions and backwards-compatible changes
keywordchangeconsequence
booleans as schemasallowable anywhere, not just "additionalProperties" and "additionalItems"true is equivalent to {}, false is equivalent to {"not": {}}, but the intent is more clear and implementations can optimize these cases more easily
"propertyNames"addedtakes a schema which validates the names of all properties rather than their values
"contains"addedarray keyword that passes validation if its schema validates at least one array item
"const"addedmore readible form of a one-element "enum"
"required"allows an empty arrayan empty array indicates that no properties are required
"dependencies"allows an empty array for property dependenciesan empty array indicates that there are no dependencies for the given property
"format": "uri-reference"addedallows relative URI references per RFC 3986; see the section below about "uri" as a format
"format": "uri-template"addedindicates an RFC 6570 conforming URI Template value, as is used in JSON Hyper-Schema for "href"
"format": "json-pointer"addedindicates a JSON Pointer value such as /foo/bar; do not use this for JSON Pointer URI fragments such as #/foo/bar: the proper format for those is "uri-reference"
"examples"addedarray of examples with no validation effect; the value of "default" is usable as an example without repeating it under this keyword
Formats: "uri" vs "uri-reference"

While not technically a change, the behavior of the "uri" format was not clearly explained and often implemented and used incorrectly (including in the draft-04 meta-schema).

"uri" should only be used when an absolute URI (starting with a scheme) is required.

When a relative path, fragment, or any other style of URI Reference (per RFC 3986) is allowable, use "uri-reference".

Implementations offering a translation from draft-04 to draft-06 may want to offer an option to convert "uri" formats to "uri-reference", although any such option should be disabled by default for strict conformance.

Q: What happened to draft-05?

The draft-05 core and validation specifications were intended to be more clear and readable rewrites of draft-04, to give us a strong base for draft-06 changes. Implementors should not implement or advertise support for "draft-05".

Implementations that supported "draft-05" by implementing proposals from right after the publication of draft-04 should either remove that support or give it a different name to avoid confusion.

Q: What happened to all the discussions around re-using schemas with "additionalProperties"?

There are several competing proposals for making the re-use of schemas that set "additionalProperties" to something other than true. Most people specifically care about the case where it is false, but the same behavior occurs with any non-true value.

All of the proposals in this area will be the focus of draft-08. While we made progress in eliminating some options during draft-07, the remaining divisions are deep enough to warrant making it the primary focus of a draft (draft-07's primary focus is Hyper-Schema).

The difficulty is that if you attempt to do this:

data
{ "type": "object", "allOf": [{ "$ref": "#/definitions/foo" }, { "$ref": "#/definitions/bar" }], "definitions": { "foo": { "properties": { "foo": { "type": "string" } }, "additionalProperties": false }, "bar": { "properties": { "bar": { "type": "number" } }, "additionalProperties": false } }}

Validation will always fail for any non-empty object instance. "additionalProperties" only knows about immediately adjacent "properties" and "patternProperties", in order to ensure that each subschema means the same thing whether it is being used with another subschema or on its own.

So in this example, if the instance has a "bar" property, it will fail the first subschema because "bar" is not "foo". If it has a "foo" property, it will fail the second subschema because "foo" is not "bar". And any other property will fail both schemas.

A workaround is available with the new "propertyNames" keyword:

data
{ "type": "object", "allOf": [{ "$ref": "#/definitions/foo" }, { "$ref": "#/definitions/bar" }], "propertyNames": { "anyOf": [ { "$ref": "#/definitions/fooNames" }, { "$ref": "#/definitions/barNames" } ] }, "definitions": { "foo": { "properties": { "foo": { "type": "string" } } }, "fooNames": { "enum": ["foo"] }, "bar": { "properties": { "bar": { "type": "number" } } }, "barNames": { "enum": ["bar"] } }}

This will allow an object with either "foo" or "bar" or both, but will fail validation if any other property is present. The "allOf" ensures that "foo" and "bar" will each be validated correctly if present, while the "anyOf" allows for properties with names in either allowed set, but forbids properties that are not listed in at least one set.

It does require duplicating the names, and the awkward use of both an "allOf" and "anyOf", but it is less repetition than other options, and can be re-used fairly robustly even if the "foo" and "bar" schemas are in separate files managed by a different person or organization.

JSON Hyper-Schema Draft-06 Release Notes

Release notes for migrating from draft-luff-json-hyper-schema-00 (draft-04) to draft-wright-json-schema-hyperschema-01 (draft-06).

NOTE: draft-07 has been released

The migration notes for draft-07 give a much more straightforward overview of migrating from draft-04 to draft-07 by skipping the complicated intermediate states of draft-05 and draft-06. This page has been retained for historical interest, but it is not recommened for those who only want to get going with the latest draft.

For implementors: We recommend only implementing draft-07, and not draft-06 or earlier.

Q: What are the incompatible changes between draft-04 and draft-06?

Between drafts 04 and 06 we undertook a major re-examining of Hyper-Schema, which has never been as widely adopted as JSON Schema Validation.

While we knew that there were still major gaps in draft-06, we felt that it was a good set of changes for collecting feedback. With draft-07 published, that draft or later should be used, and draft-06 becomes an historical curiosity.

Changes from draft-04 to draft-05
keywordchangeconsequence
"base"replaces looking up the nearest "self" link to determine the base URI for "href"if you were relying on "self" links to change the base, set "base" explicitly
"rel""full" relation removeduse "item"
"rel""instances" and "create" relations removeduse "collection"
"rel""root" relation removeduse a fragment in your "href" URI Template
"fragmentResolution"removedmedia type determines how fragments are interpreted
"pathStart"removed[no replacement]
"method"changed back to HTML form semantics of "get" and "post" rather than all HTTP methods[changed again in draft-06 due to feedback that this was confusing]
Changes from draft-05 to draft-06
keywordchangeconsequence
"method"removedfor HTTP method proposals, see issues #73 and #296 (use either "method" or "allow" as an extension keyword if needed); indication of how to use "schema" and "encType" no longer necessary
"schema"removeduse "hrefSchema", "submissionSchema", or "targetSchema"
"encType"removeduse "submissionEncType" for request bodies; no longer needed for URI query strings
"hrefSchema"addedreplaces "method": "get", "schema": {...}, with additional functionality
"submissionSchema"addedreplaces "method": "post", "schema": {...}
"submissionEncType"addedreplaces "method": "post", "encType": "..."
"href"preprocessing removedto be replaced and expanded in future drafts
Proper use of "targetSchema"

Although 'targetSchema' has kept its meaning, its interpretation has varied. Therefore, using it as intended might feel like a modification

Due to draft-04 emphasizing individual HTTP methods as "method" values, many users interpreted "targetSchema" as a hint of the response to the method in "method". This was never correct; all drafts define this keyword as describing the representation of the target resource, which appears as a response to HTTP GET, but may or may not appear in other responses.

Draft-06 clarifies this usage and provides guidance on its use with different HTTP methods. This includes using "targetSchema" as a request description for PUT and PATCH. With draft-04, many users used "schema" to describe PUT and PATCH requests which is not needed.

However, the "targetHints" proposal has been accepted into draft-07. Among other things, it enables hinting at "Accept-Patch", which is needed to properly use "targetSchema" with HTTP PATCH. There will be examples and detailed guidance in draft-07.

Q: Why were several major changes made to Hyper-Schema just before draft-06's publication?

A: During final review, it became apparent that there was no consensus on how to use the spec as written. The late changes were necessary to publish a spec with unambiguous meaning, so that we could get feedback on its contents rather than differing interpretations. Originally we attempted to simply clarify what was there, but then we realized there was no agreement on what was there in the first place.

Q: Why doesn't the spec mention or behave like HTML anymore?

A: We came to a consensus that the existing analogies caused more harm than good, for two reasons:

  1. The change between draft-03 and draft-04 to let "method" indicate any HTTP method instead of HTML's <form method="..."> "get" and "post" values broke the original analogy to HTML, and trying to change it back was not well-received
  2. Only being able to use "schema" and "encType" for either the URI query string (but no other part of the URI) or the request body, but not having any way to work with both at once, was overly restrictive for API design
Splitting "schema"

Instead of having "schema" perform two different things depending on "method", we split it into two keywords, one for each use. This allows using both simultaneously when needed, which is a use case not present in HTML forms.

"hrefSchema" replaces the "method": "get" use, but leverages URI Template variables so that client data-driven dynamic URIs are no longer limited to the query string. "encType" is no longer needed with this approach.

"submissionSchema" directly replaces the "method": "post" use, with "submissionEncType" replacing "encType".

Removing "method"

Draft-05 tried to restore the draft-03 behavior of "method", but feedback told us that users found the change very confusing. With "schema" split, the draft-05 behavior of "method" was no longer needed.

We could have switched by to draft-04's "method" behavior, but in addition to producing more confusion from all of the back and forth, the draft-04 approach to "method" was not consistent with the rest of the LDO design anyway. Most notably, it caused problems with the usage of "targetSchema" as described above.

A: Ideally, this is implicitly conveyed by your link relation type, which is the primary indicator of semantics across machine-oriented hypermedia in general. RFC 5988 provides guidance on creating custom (a.k.a. "extension") link relations.

Several URI schemes and namespaces, such as the UUID namespace in the urn: scheme, or the tag: scheme, are particularly suitable for creating unique identifiers.

And of course, there are ways to detect this at runtime such as HTTP's "Allow" response header, or attempting a method and handling a 405 Method Not Allowed error accordingly.

If you need to explicitly indicate which HTTP methods are supported, you can use 'targetHints' from draft-07 as an extension to draft-06.

Q: If "targetSchema" is not the response, how do I describe responses?

A: You should have hyper-schemas for your various success and error responses, but connecting them to links is more of a documentation question than a usage question: each response will indicate its own schema, so you don't need to know it in advance at runtime.

There has never been a Hyper-Schema keyword to explicitly associate responses with operations such as HTTP methods. The use cases for this seem to be about generating API documentation, so this is most likely a candidate for a JSON Schema API Documentation vocabulary.

Need Help?

Did you find these docs helpful?

Help us make our docs great!

At JSON Schema, we value docs contributions as much as every other type of contribution!

Still Need Help?

Learning JSON Schema is often confusing, but don't worry, we are here to help!.