jsonref.org

JSON REFERENCE v0.4.0

OVERVIEW

JSON alone can only capture tree structured objects. JSON Reference (or JsonRef) is a standard way to represent references in JSON documents, to allow graph structured objects to be stored as JSON. Conceptually, JSON Reference extends pure JSON decoding/encoding by parsing any JSON reference ($ref) occurrences to native language dependent reference types after decoding, and normalizing references in a JSON reference compatible way before encoding (some implementations may only support dereferencing):

                                           object
                                            ___
                        .-------------.    |   |\     .---------.
               .------->| Normalize   |--->|   '-|--->| Encode  |-------.
               |        |             |    |     |    |         |       |
               |        '-------------'    |_____|    '---------'       |
               |                                                        v
            object                         object                    string
             ___                            ___                       ___
    (\_/)   |   |\      .-------------.    |   |\     .---------.    |   |\
    (O.o)   |   '-|     | Dereference |    |   '-|    | Decode  |    |   '-|
    (> <)   |     |<----|             |<---|     |<---|         |<---|     |
            |_____|     '-------------'    |_____|    '---------'    |_____|

This specification defines JSON Reference v0.4.0. JSON Reference v0.4.0 succeeds JSON Reference v0.3.0 and is not entirely backwards compatible. JSON Reference v0.4.0 relies on the JSON Pointer v0.4.0 specification. This specification is hosted on Github.

SPECIFICATION

Every valid JSON Reference document is a valid JSON document. JSON Reference makes use of four special object properties meaningful to JSON Reference, but not meaningful to JSON: $ref, $id and optionally $refProp, $idProp:

$id

$ref

$idProp, $refProp

References and replacement-values

Lazy dereferencing

Lazy dereferencing of $ref objects in a decoded JSON document may be supported. Lazy dereferencing attempts to dereference $ref objects “as needed”. How “as needed” is defined is dependent on the application. All the above rules still apply. The only difference between lazy and canonical (upfront) dereferencing is when errors are detected and raised to the client. Implementations that use or support lazy dereferencing should make it clear when, how, and if lazy dereferencing is being performed.

Normalizing references to JSON encodable objects

This JSON Reference specification provides no strict guidance on how to encode native objects containing references to JSON Reference compatible JSON documents. Of course, this can still be done. The only requirement is that the resulting JSON is actually encodable (tree structured) and uses Json Reference keywords in a manner consistent with this specification.

WHAT JSON REFERENCE IS NOT

JSON Reference is not JSON Merge or JSON Patch and supporting object merging is beyond the scope of the specification. The focus of the specification is simply encoding objects with references to themselves.

JSON Reference is not JSON Schema draft v06+’s JSON Reference like dereferencing implementation, although it has been suggested as a replacement for it.

JSON SCHEMA STYLE JSON REFERENCE CONFORMANCE

Like JSON Schema draft v06+ specifications, this implementation breaks with the original JSON Reference specifications in using $id (by default) instead of id for object identifiers. However, this specification diverges with the canonical JSON Schema specification of references:

NOTES FOR JSON REFERENCE v0.4.0 IMPLEMENTORS

$id pointers

According to JSON Reference v0.3.0, the JSON reference fragment part must be a JSON Pointer. Another commonly implemented type of reference is a reference to an object that has an $id field as described above. JSON Schema for example, requires such references. The specification extends the previous specification by adding explicit support for this reference type (described above). Example:

{
  "foo": "bah",
  "a": {
    "$id": "#foo"
  },
  "b": {
    "byid": { "$ref": "#foo" },
    "byref": { "$ref": "#/foo" }
  }
}

Gives:

...
"b": {
  "byid": { "$id: "#foo" },
  "byref": "bah"
}

Pointers to pointers

In general circular references are allowed and useful for defining graph like structures - which is the whole point in JSON Reference. However, consider:

{
  "foo": { "$ref": "#/bah" },
  "bah": { "$ref": "#/foo" }
}

{ "$ref": "#/ }

Neither document makes sense because they are vacuous: the references are expected to refer to valid content, they are not content in an of themselves, so in these cases no valid value can ever be resolved, and the document is erroneous (raise error). On the other hand, all of the following are fine:

{
  "foo": { "$ref": "#/bah" },
  "bah": { "$ref": "#/" }
}

{
  "foo": { "$ref": "#/" }
}

{
  "definitions": {
    "foo": { "properties": { "bar": { "$ref": "#/definitions/bar" } } },
    "bar": { "properties": { "foo": { "$ref": "#/definitions/foo" } } }
  },
  "type": "object",
  "properties": { "foo": { "$ref": "#/definitions/foo" } }
}

In summary, pointers to pointers are fine, but pointers to pointers resulting in a pure pointer loop are erroneous. Conceptually, if one can collapse any pointer to pointer chain into an eventual non pointer replacement-value dereferencing should succeed, if not an error must be raised.

Pointers that point through other pointers

Consider the following document:

{
  "a": {
    "x": { "$ref": "#/b/x" }
  },
  "b": { "$ref": "#/c" },
  "c": {
    "x": "Hey you found me!"
  }
}

#/b/x points through the reference at #/b. For this to work, we must ensure #/b is resolved before #/b/x.

Refs to non-structural types

This:

{
  "a": 1,
  "b": { "$ref": "#/a" }
}

should give a dereferenced object like:

{
  "a": 1,
  "b": 1
}

Whether a and b actually reference the same storage location or a copy is implementation dependent (as explained above). Implementations may choose to allow the client to configure either behavior.

ADDENDUM

Bundling Multiple Documents

It’s often the case that one JSON Reference document will refer to parts of, or all of another document identified by a absolute URI. In such cases it is convenient to distribute all the required documents in a single “bundle”. Bundling is also a way to avoid having to load required documents from remote locations at dereferencing time. A suggested solution is to simply bundle multiple documents either:

It is upto the implementation to identify and parse such bundles and load resource from the bundle rather than remote resource locations. Clients should be required to explicitly request this loading behaviour.

The above does not imply other bundling and/or local caching solutions are prohibited.