This document is also available in this non-normative format: diff to previous version
Copyright © 2010-2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
JSON [RFC4627] has proven to be a highly useful object serialization and messaging format. JSON-LD [JSON-LD] harmonizes the representation of Linked Data in JSON by outlining a common JSON representation format for expressing directed graphs; mixing both Linked Data and non-Linked Data in a single document. This document outlines an Application Programming Interface and a set of algorithms for programmatically transforming JSON-LD documents in order to make them easier to work with in programming environments like JavaScript, Python, and Ruby.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document has been under development for over 18 months in the JSON for Linking Data Community Group. The document has recently been transferred to the RDF Working Group for review, improvement, and publication along the Recommendation track. The specification has undergone significant development, review, and changes during the course of the last 18 months.
There are several independent interoperable implementations of this specification. There is a fairly complete test suite and a live JSON-LD editor that is capable of demonstrating the features described in this document. While development on implementations, the test suite and the live editor will continue, they are believed to be mature enough to be integrated into a non-production system at this point in time with the expectation that they could be used in a production system within the next year.
It is important for readers to understand that the scope of this document is currently under debate and new features may be added to the specification. Existing features may be modified heavily or removed entirely from the specification upon further review and feedback from the broader community. This is a work in progress and publication as a Working Draft does not require that all Working Group members agree on the content of the document.
There are a number of ways that one may participate in the development of this specification:
This document was published by the RDF Working Group as an Editor's Draft. If you wish to make comments regarding this document, please send them to public-rdf-comments@w3.org (subscribe, archives). All feedback is welcome.
Publication as an Editor's Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This section is non-normative.
This document is a detailed specification for an Application Programming Interface for the JSON-LD Syntax. The document is primarily intended for the following audiences:
To understand the basics in this specification you must first be familiar with JSON, which is detailed in [RFC4627]. You must also understand the JSON-LD Syntax [JSON-LD], which is the base syntax used by all of the algorithms in this document. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ECMA-262] and WebIDL [WEBIDL]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [RDF-CONCEPTS].
This section is non-normative.
The JSON-LD Syntax specification [JSON-LD] outlines a language that may be used to express Linked Data in JSON. Often, it is useful to be able to transform JSON-LD documents so that they may be easily processed in various programming environments.
There are four major types of transformation that are discussed in this document: expansion, compaction, flattening, and RDF conversion.
This section is non-normative.
Software algorithms are easiest to write when the data that they are processing have a regular form. Since information can be represented by JSON-LD in a variety of different ways, transforming all of these methods into a uniform structure allows the developer to simplify their processing code. For example, note that the following input uses only terms and is fairly compact:
{
  "@context": {
    "name": "http://xmlns.com/foaf/0.1/name",
    "homepage": {
      "@id": "http://xmlns.com/foaf/0.1/homepage",
      "@type": "@id"
    }
  },
  "@id": "http://me.markus-lanthaler.com/",
  "name": "Markus Lanthaler",
  "homepage": "http://www.markus-lanthaler.com/"
}The next input example uses one IRI to express a property, but leaves the rest of the information untouched.
{
  "@context": {
    "homepage": {
      "@id": "http://xmlns.com/foaf/0.1/homepage",
      "@type": "@id"
    }
  },
  "@id": "http://me.markus-lanthaler.com/",
  "http://xmlns.com/foaf/0.1/name": "Markus Lanthaler",
  "homepage": "http://www.markus-lanthaler.com/"
}While both inputs are valid JSON-LD, writing a program to handle every permutation of possible inputs can be difficult, especially when the incoming context could change as well. To ensure that the data can be given a more uniform structure, JSON-LD introduces the notion of expansion. Expansion performs two important operations. The first is to expand all values that represent IRIs to absolute IRIs. The second is to express all values in expanded form. Running the Expansion algorithm against the examples provided above results in the following output:
[
  {
    "@id": "http://me.markus-lanthaler.com/",
    "http://xmlns.com/foaf/0.1/name": [
      { "@value": "Markus Lanthaler" }
    ],
    "http://xmlns.com/foaf/0.1/homepage": [
      { "@id": "http://www.markus-lanthaler.com/" }
    ]
  }
]Note that in the output above all context definitions have been removed, all terms and prefixes have been expanded to absolute IRIs, and all JSON-LD values are expressed in expanded form. While the output is more difficult for a human to read, it is easier for a software program to process because of its very regular structure.
This section is non-normative.
While expansion expands a given input as much as possible, compaction performs the opposite operation: it expresses a given input as succinctly as possible. In contrast to expansion which is meant to produce something that is easy to process by software programs, compaction is meant to produce something that is easy to read by software developers. Compaction uses a developer-supplied context to compress IRIs to terms or compact IRIs and JSON-LD values expressed in expanded form to simple values such as strings and numbers.
For example, assume the following expanded JSON-LD input document:
[
  {
    "@id": "http://me.markus-lanthaler.com/",
    "http://xmlns.com/foaf/0.1/name": [
      { "@value": "Markus Lanthaler" }
    ],
    "http://xmlns.com/foaf/0.1/homepage": [
      { "@id": "http://www.markus-lanthaler.com/" }
    ]
  }
]Additionally, assume the following developer-supplied JSON-LD context:
{
  "@context": {
    "name": "http://xmlns.com/foaf/0.1/name",
    "homepage": {
      "@id": "http://xmlns.com/foaf/0.1/homepage",
      "@type": "@id"
    }
  }
}Running the Compaction Algorithm given the context supplied above against the JSON-LD input document provided above would result in the following output:
{
  "@context": {
    "name": "http://xmlns.com/foaf/0.1/name",
    "homepage": {
      "@id": "http://xmlns.com/foaf/0.1/homepage",
      "@type": "@id"
    }
  },
  "@id": "http://me.markus-lanthaler.com/",
  "name": "Markus Lanthaler",
  "homepage": "http://www.markus-lanthaler.com/"
}Note that all IRIs have been compacted to
    terms as specified in the context
    which consequently has been injected into the output. While compacted
    output is most useful to humans, it can often also be used to generate
    structures that are easy to program against. Compaction enables developers
    to map any expanded document into an application-specific compacted document.
    While the context provided above mapped http://xmlns.com/foaf/0.1/name
    to name, it could have also have been mapped to any other term
    provided by the developer.
This section is non-normative.
While expansion ensures that a document is in a uniform structure, flattening goes a step further and ensures that also the shape of the data is deterministic. In expanded documents properties of a single node may still be spread across a number of different JSON objects. By flattening a document, all properties of a node are collected in a single JSON object and all blank nodes are labeled with a blank node identifier. Often this drastically simplifies the code to process JSON-LD data.
For example, assume the following JSON-LD input document:
{
  "@context": {
    "name": "http://xmlns.com/foaf/0.1/name",
    "knows": "http://xmlns.com/foaf/0.1/knows"
  },
  "@id": "http://me.markus-lanthaler.com/",
  "name": "Markus Lanthaler",
  "knows": [
    {
      "name": "Manu Sporny",
      "knows": {
        "@id": "http://greggkellogg.net/foaf#me"
      }
    },
    {
      "@id": "http://greggkellogg.net/foaf#me",
      "name": "Gregg Kellogg"
    }
  ]
}Running the Flattening Algorithm with a context set to null to prevent compaction returns the following document:
[
  {
    "@id": "http://me.markus-lanthaler.com/",
    "http://xmlns.com/foaf/0.1/name": [
      { "@value": "Markus Lanthaler" }
    ],
    "http://xmlns.com/foaf/0.1/knows": [
      { "@id": "_:t0" },
      { "@id": "http://greggkellogg.net/foaf#me" }
    ]
  },
  {
    "@id": "_:t0",
    "http://xmlns.com/foaf/0.1/name": [
      { "@value": "Manu Sporny" }
    ],
    "http://xmlns.com/foaf/0.1/knows": [
      { "@id": "http://greggkellogg.net/foaf#me" }
    ]
  },
  {
    "@id": "http://greggkellogg.net/foaf#me",
    "http://xmlns.com/foaf/0.1/name": [
      { "@value": "Gregg Kellogg" }
    ]
  }
]Note how in the output above all properties of a node are collected in a
    single JSON object and how the blank node representing
    "Manu Sporny" has been assigned the blank node identifier
    _:t0.
To make it easier for humans to read such a flattened document can be compacted by passing a context. Using the same context as the input document, the flattened and compacted document looks as follows:
{
  "@context": {
    "name": "http://xmlns.com/foaf/0.1/name",
    "knows": "http://xmlns.com/foaf/0.1/knows"
  },
  "@graph": [
    {
      "@id": "http://me.markus-lanthaler.com/",
      "name": "Markus Lanthaler",
      "knows": [
        { "@id": "_:t0" },
        { "@id": "http://greggkellogg.net/foaf#me" }
      ]
    },
    {
      "@id": "_:t0",
      "name": "Manu Sporny",
      "knows": {
        "@id": "http://greggkellogg.net/foaf#me"
      }
    },
    {
      "@id": "http://greggkellogg.net/foaf#me",
      "name": "Gregg Kellogg"
    }
  ]
}Please note that the flattened and compacted result will always explicitly
    designate the default by the @graph member in the top-level
    JSON object. Compaction optimizes that
    member away if its value contains just one item.
This section is non-normative.
JSON-LD can be used to serialize data expressed in RDF as described in [RDF-CONCEPTS]. This ensures that data can be round-tripped from and to any RDF syntax without any loss in the fidelity of the data.
For example, assume the following RDF input serialized in Turtle [TURTLE-TR]:
<http://me.markus-lanthaler.com/> <http://xmlns.com/foaf/0.1/name> "Markus Lanthaler" . <http://me.markus-lanthaler.com/> <http://xmlns.com/foaf/0.1/homepage> <http://www.markus-lanthaler.com/> .
Using the Convert from RDF Algorithm a developer could transform this document into expanded JSON-LD:
[
  {
    "@id": "http://me.markus-lanthaler.com/",
    "http://xmlns.com/foaf/0.1/name": [
      {
        "@value": "Markus Lanthaler"
      }
    ],
    "http://xmlns.com/foaf/0.1/homepage": [
      {
        "@id": "http://www.markus-lanthaler.com/"
      }
    ]
  }
]Note that the output above could easily be compacted using the technique outlined in the previous section. It is also possible to transform the JSON-LD document back to RDF using the Convert to RDF Algorithm.
All examples and notes as well as sections marked as non-normative in this specification are non-normative. Everything else in this specification is normative.
The keywords must, must not, required, should, should not, recommended, may, and optional in this specification are to be interpreted as described in [RFC2119].
There are two classes of products that can claim conformance to this specification: JSON-LD Implementations and JSON-LD Processors.
A conforming JSON-LD Implementation is a system capable of transforming JSON-LD documents according the algorithms defined in this specification.
A conforming JSON-LD Processor is a conforming JSON-LD Implementation that exposes the application programming interface (API) defined in this specification.
The algorithms in this specification are generally written with more concern for clarity than over efficiency. Thus, JSON-LD Implementations and Processors may implement the algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.
This specification does not define how JSON-LD Implementations or Processors handle non-conforming input documents. This implies that JSON-LD Implementations or Processors must not attempt to correct malformed IRIs or language tags; however, they may issue validation warnings.
Implementers can partially check their level of conformance to this specification by successfully passing the test cases of the JSON-LD test suite [JSON-LD-TESTS]. Note, however, that passing all the tests in the test suite does not imply complete conformance to this specification. It only implies that the implementation conforms to aspects tested by the test suite.
This document uses the following terms as defined in JSON [RFC4627]. Refer to the JSON Grammar section in [RFC4627] for formal definitions.
@context where the value, or the @id of the
      value, is null explicitly decouples a term's association
      with an IRI. A key-value pair in the body of a JSON-LD document whose
      value is null has the same meaning as if the key-value pair
      was not defined. If @value, @list, or
      @set is set to null in expanded form, then
      the entire JSON object is ignored.Furthermore, the following terminology is used throughout this document:
_:.All algorithms described in this section are intended to operate on language-native data structures. That is, the serialization to a text-based JSON document isn't required as input or output to any of these algorithms and language-native data structures must be used where applicable.
@context keyword.@value, @list,
          or @set keywords, or@graph keyword.@list
      member.The algorithm takes three input variables: an active context,
    an active property, and an element to be expanded. To
    begin, the active context is set to the result of performing, Context Processing on the passed
    expandContext,
    or empty if expandContext
    is null, active property is set to null, and
    element is set to the JSON-LD input. This algorithm expects the
    JSON-LD input to be a well-formed JSON-LD document as defined in [JSON-LD].
@list and the expanded
          item is an array or a list object trigger
          a LIST_OF_LISTS_DETECTED error.@context member, update the
          active context according to the steps outlined in
          Context Processing and remove the
          @context member.true for
               the vocabRelative flag).@id, set the @id
                  member of result to the result of expanding value
                  according the IRI Expansion algorithm (passing true
                  for the documentRelative flag). If value is not a string
                  trigger an INVALID_ID_VALUE error.@type, set the @type
                  member of result to the result of expanding value
                  according the IRI Expansion algorithm (passing true
                  for both the documentRelative and the vocabRelative flag). If value
                  is neither a string nor an array of
                  strings trigger an INVALID_TYPE_VALUE
                  error. Empty arrays are ignored.@value, set the @value
                  member of result to value. If value is neither a scalar
                  nor null trigger an INVALID_VALUE_OBJECT_VALUE error.@language, set the @language
                  member of result to the lowercased value. If value is not
                  a string, trigger an INVALID_LANGUAGE_VALUE error.@annotation, set the @annotation
                  member of result to value. If value is not a string
                  trigger an INVALID_ANNOTATION_VALUE error.@set or @list, set the
                  expanded property member of result to the result of expanding value by
                  recursively using this algorithm, passing copies of the active context and
                  active property.@graph, set the @graph
                  member of result to the result of expanding value by
                  recursively using this algorithm, passing copies of the active context and
                  @graph as active property.@language
              @value set to the currently
                      processed item and @language set to the lowercased key.
                      If val is not a string, trigger a
                      LANGUAGE_MAP_INVALID_VALUE error. Otherwise append
                      the object to language map values.@annotation
              @annotation set to
                      key if no such member exists yet and append the resulting
                      JSON object to annotation map values.@list and
              value is either not an JSON object or a JSON object
              without an @list member, replace value with a
              JSON object with an @list member whose value is set to
              value (wrapped in an array if it is not already one).@annotation member, decrease numProperties
          by 1.@value member,
          @language member, decrease numProperties
              by 1 and check that the value of the @value member is a string. If not,
              trigger an INVALID_LANGUAGE_TAGGED_STRING error.@type member, decrease
              numProperties by 1 and check that the value of the @type member is a
              string. If not, trigger an INVALID_TYPED_VALUE error.INVALID_VALUE_OBJECT error.@value member equals null, set
              element to null.@type member whose value is not an array,
          transform it to an array.@list or @set member and
          numProperties is greater than 1, trigger an
          INVALID_SET_OR_LIST_OBJECT error.@set member, set element to
          the value of that member.@language member, set element
          to null.If, after the algorithm outlined above is run, the resulting element is an
    JSON object with just a @graph member, element is set to
    the value of @graph's value. Finally, if element is a JSON object,
    it is wrapped into an array.
Processing of JSON-LD data structure is managed recursively. During processing, each rule is applied using information provided by the active context.
The active context contains the active term definitions
    which specify how properties and values have to be interpreted as well as the current
    vocabulary mapping and the default language. Each term definition consists
    of an IRI mapping and optionally a type mapping from terms to datatypes or
    language mapping from terms to language codes, and a container mapping. If an
    IRI mapping maps a term to multiple 
If a local context is encountered, information from the local context
    is merged into the active context. A local context is identified within
    a JSON object having a @context member with a string,
    array or a JSON object value.
This algorithm specifies how the active context is updated with a local context. The algorithm takes three input variables: an active context, a local context, and an array of already included remote contexts remoteContexts. To begin, remoteContexts is initialized to an empty array.
All calls of the IRI Expansion algorithm pass the value specified in the
    algorithm along with the active context, the currently being processed local context,
    and true for the vocabRelative flag.
RECURSIVE_CONTEXT_INCLUSION error. Otherwise, add
              context to remoteContexts.@context member recursively invoke
              this algorithm passing a copy of active context, the value of the
              @context member as local context, and a copy of
                the remoteContexts array. Relative IRIs
                are expanded using the remote context's IRI. Otherwise raise an
                INVALID_REMOTE_CONTEXT error.INVALID_LOCAL_CONTEXT error.@vocab member: if its value is neither
              an absolute IRI, i.e., it does not contain a colon (:),
              nor null, trigger an INVALID_VOCAB_MAPPING
              error; otherwise set the active context's
              vocabulary mapping to its value and remove the @vocab
              member from context.@language member: if its value is neither
              a string nor null, trigger an
              INVALID_DEFAULT_LANGUAGE error; otherwise set the
              active context's default language to
              its value and remove the @language member from context.INVALID_TERM_DEFINITION error@id member with a value val:
                  INVALID_PROPERTY_GENERATOR 
                          error.
                        @type member with a value val and val
                  is not a string or does not expand to an absolute IRI using the
                  IRI Expansion algorithm, raise an
                  INVALID_TYPE_MAPPING error. Otherwise set the
                  IRI mapping of definition to the expanded val.@language member with a value val
                  that is a string or null, set the language mapping of
                  definition to the lowercased val. If val is neither a
                  string nor null, raise an
                  INVALID_LANGUAGE_MAPPING error.@container member with a value val that
                  equals @list, @set, or @annotation, set the
                  container mapping of definition to val.
                  If val is not one of those values, raise an
                  INVALID_CONTAINER_MAPPING error.In JSON-LD documents keys and some values are evaluated to produce an IRI. This section defines an algorithm for transforming strings representing an IRI into an absolute IRI. If IRI expansion occurs during context processing, the local context that is being processed is passed to this algorithm. After application of this algorithm, values processed by this algorithm are said to be in expanded IRI form, although this may also include blank node identifiers and JSON-LD keywords.
The algorithm takes two mandatory and four optional input variables: a value
    to be expanded, an active context, two flags documentRelative and
    vocabRelative specifying whether value should be interpreted as
    relative IRI against the document's base IRI or the
    active context's vocabulary mapping,
    along with an local context passed when this algorithm is used in
    Context Processing, and finally an array
    path which is used to detect cyclic IRI mappings.
    If not passed, the two flags are set to false and path is
    initialized to an empty array by default.
The algorithm for generating an IRI is:
CYCLIC_IRI_MAPPING error. Otherwise append value
          to path.true for the vocabRelative flag. If the result
          is a property generator, raise an
          PROPERTY_GENERATOR_IN_TERM_DEFINITION error.:), perform the following steps:
      :).// or prefix equals _,
          return value as is.true for the
          vocabRelative flag. If the expanded prefix contains a colon (:)
          generate and return an IRI by prepending the expanded prefix to the
          (possibly empty) suffix using textual concatenation.true and the
      active context contains a vocabulary mapping, generate and return an
      IRI by prepending the IRI of the vocabulary mapping
      to the value using textual concatenation.true, resolve value
      against the base IRI as per [RFC3986] and return the resulting IRI. Only the basic
      algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization
      nor Scheme-Based Normalization (as described in sections 6.2.2 and 6.2.3 of [RFC3986])
      are performed. Characters additionally allowed in IRI references are treated in the same way that
      unreserved characters are treated in URI references, per section 6.5 of [RFC3987]If the result of the algorithm above is a blank node identifier, i.e., a string that begins with
    _:, and no local context has been passed,
    generated a new blank node identifier before returning the
    final result.
Some values in JSON-LD can be expressed in a compacted form. These values are required to be expanded at times when processing JSON-LD documents. A value is said to be in expanded form after the application of this algorithm.
The algorithm for expanding a value takes an active property and active context. It is implemented as follows:
@graph or the
      active property's type mapping is set to
      @id, add a key-value pair to result where the key is @id
      and the value is the result of expanding value according to the
      IRI Expansion algorithm passing true for the
      documentRelative flag. Then return result.@value
      and the value is value.@type and the value is the
      IRI associated with the type mapping or a newly
      generated blank node identifier if the
      type mapping is set to a blank node identifier.@language and the value is the
      language tag associated with the language mapping or the active property or the
      default language.The algorithm takes a single input variable: an element to be labeled with blank node identifiers.
@list member, recursively apply this algorithm to all items
      of the @list member's value.@id member,
          create a new @id member and assign it a new
          blank node identifier according the
          Generate Blank Node Identifier algorithm.This algorithm is used to generate new
    blank node identifiers or to relabel existing
    blank node identifiers with a new one to avoid
    collision by the introduction of new ones. It needs to keep an identifier map,
    a counter, and a prefix between its executions to be able to generate new
    blank node identifiers. The counter
    is initialized to 0 and prefix is set to _:t by default.
The algorithm takes a single input variable identifier which might be null.
1.The algorithm takes four input variables: an active context, an inverse context, an active property, and an element to be compacted. To begin, the active context is set to the result of performing Context Processing on the passed context, inverse context is set to the result of creating an inverse context from the active context, active property is set to null, and element is set to the result of performing the Expansion Algorithm on the JSON-LD input.
compactArrays
          option is set to true, return that item; otherwise return
          result.@value or @id member,
      replace element with the result of the
      Value Compaction algorithm. If the updated
      element is a scalar, return it as it cannot be further
      compacted.@id, compact value
              according the rules of the IRI Compaction algorithm.@type, compact value
              (or each item of value if it is an array) according the rules of the
              IRI Compaction algorithm with the
              vocabRelative flag set to true. If value is an
              array consisting of just one item, replace value with that item.@graph, compact value
              by recursively invoking this algorithm, passing a copy of the active context,
              inverse context, and property as active property
              ensuring that the result is an array.true.true.@language or @annotation
          @language or
              @annotation member of item (depending on the value of the
              active property's container mapping).@list member,
          @list, set the active property member of result
              to the value of item's @list member. If such an member already exists
              in result, raise an COMPACTION_TO_LIST_OF_LISTS error; otherwise
              continue with the next property-value pair from element.compactArrays
          option is set to false or the active property's
          container mapping is set to @list or @set, convert the
          value of the active property member of result to an array if
          it is not one already.If, after the algorithm outlined above is run, the resulting element is an array
    replace it with a new JSON object with a single member whose name is the result of
    compacting the value @graph with the IRI Compaction algorithm
    and whose value is element. Finally, add a @context property to element
    and set it to the initially passed context.
This section defines an algorithm for transforming an IRI to a term or compact IRI. If a value is passed it is used to choose the best matching term.
This algorithm takes three mandatory and two optional parameters. The mandatory
    parameters are the iri to be compacted, an active context,
    and an inverse context. Optionally it is possible to pass a value
    and a vocabRelative flag which specifies whether the passed iri
    should be compacted using the active context's
    vocabulary mapping. If the vocabRelative flag is not set
    it defaults to false.
The algorithm for generating a compact IRI is:
@set, typeOrLanguage, and typeLanguageValue
              to null.@annotation member, set container to
                  @annotation.@id member, set
                  typeOrLanguage to @type and typeLanguageValue
                  to @id.@value member,
                  @type member, set typeOrLanguage to
                      @type and typeLanguageValue to the value of the
                      @type member of value.@language member, set
                      typeOrLanguage to @language and
                      typeLanguageValue to the value of the @language
                      member of value. If value has no @annotation
                      member, set container to @language@value
                      member is is a string, set typeOrLanguage to
                      @language and typeLanguageValue to
                      @null.@list member,
                  @list member has at least one item, update
                      container, typeOrLanguage, and
                      typeLanguageValue by recursively running the steps
                      2.1.2 to
                      2.1.3.4 (which will never be true since list of lists are not
                      allowed) of this algorithm passing the first item of value's
                      @list member as new value.@annotation member, set
                      container to @list.@list
                      member, recursively run the steps
                      2.1.2 to
                      2.1.3.4 (which will never be true since list of lists are not
                      allowed) of this algorithm passing the item as new value. If
                      the resulting typeOrLanguage or typeLanguageValue
                      differ from the current value of typeOrLanguage or
                      typeLanguageValue, set both to null and stop
                      processing the @list items.@list, set the first item of
              queryPath to an array consisting of the two elements
              @list and null; otherwise set it to an array
              consisting of three elements where the first element is the value of container
               and the other two elements are @set and @null.@null.@null. Set the
              third item of queryPath to an array whose first element
              typeLanguageValue and whose second element is @null.term member, return result.term member, return its value.term member, i.e., it is
          a property generator, continue with the next termIri-termDefinition
          pair from inverse context.term member of termDefinition with a colon
          (:) character and the unmatched part of iri.term member of result to the compact IRI
          and return result.true, the
      active context has a vocabulary mapping, and iri
      begins with the IRI of the vocabulary mapping but is longer
      term member of result to
          vocabIri and return result.term member of result to iri and
      return result.An active context as produced by the Context Processing algorithm is very efficient for expanding terms and compact IRIs to IRIs but is of limited use for the opposite operation: IRI compaction. Hence, this algorithm introduces the notion of an inverse context which brings the same efficiency to IRI compaction. An inverse context a tree of JSON objects which allow to efficiently select a term for a IRI-value pair.
The value takes an active context and returns the corresponding inverse context.
@null.@null if no such mapping exists.propertyGenerators.term and append the
          term to the term member of the JSON object for
          the term's IRI in inverse context
          (append term to inverseContext[iri]['term']).inverseContext[iri][container]['@type'][type][termType], e.g.,
              inverseContext['http://...']['@list']['@type']['http://...']['term'].@null. Then append the term to
              inverseContext[iri][container]['@language'][language][termType], e.g.,
              inverseContext['http://...']['@list']['@language']['de']['term'].inverseContext[iri][container]['@null']['@null'][termType] as well as
              inverseContext[iri][container]['@language'][defaultLanguage][termType]
              to take the default language into consideration for terms without
              explicit language mapping.term member in inverse context. The result is thus a single
      string value.propertyGenerators member in
      inverse context lexicographically (shortest terms come
      first).It is possible that multiple terms that differ in their container, type, or language mapping are mapped to the same IRI. The purpose of this algorithm is to query the inverse context to return either the best matching term, or a list of potential property generators along with a term to fall back to if none of the property generators can be applied.
This algorithm takes an inverseContextSubtree, a queryPath
    as generated by the IRI Compaction algorithm
    and a level parameter which is initialized to 0 if nothing else
    is passed. The algorithm returns either a string representing the best matching
    term or a JSON object consisting of a
    propertyGenerators member, containing a sorted array of
    potential property generators,
    and an optional term member containing a term to fall back
    to if none of the property generators
    can be applied.
3, i.e., the deepest nested
      JSON object in the inverse context has been reached,
      perform the following steps:
      propertyGenerators member,
          copy that member into a new JSON object and store that object in
          result.term member and
          result is null, return the value of that member;
          otherwise result is a JSON object, copy the term
          member into result and return result.queryPath[level]), perform the following steps:
      1
          as new level.propertyGenerators member is set to an empty array
          and whose term member is set to tmpResult.propertyGenerator member of
          tmpResult to the propertyGenerator member of result
          unless it is already in result's member. If result has no
          term member but tmpResult does, copy tmpResult's
          term member into result.Expansion transforms all values into expanded formin JSON-LD. This algorithm does the opposite, it compacts an algorithm according the term definition of the passed active property. After the application of this algorithm a value is said to be in compacted form.
This algorithm takes a value, an active context, an inverse context, an active property, and an optional containerValue.
@annotation and value
      has an @annotation member which equals containerValue, remove that member.@id,
      return the result of performing IRI Compaction on that
      member's value.@value
      member, perform the following steps:
      @type member, remove the @type member
          from value.@language member, remove the
          @language member from value.@language, and value has
          a @language member which equals containerValue, remove the
          @language member from value.@language member, remove the
              @language member from value.@value member is a
              string, return value.@value member, return the value of that
          member.This algorithm checks if a specific value exists for all IRIs associated with a property generator and if so, it removes them. The algorithm takes five parameters: element, property, value, active context, active property.
propertyGenerators member of active property perform
      the following steps:
      @id member exists (i.e., it is
          an unlabeled blank node, in that case node objects are never
          considered to be equal.
          term member of active property
      since no matching property generator has been found.The algorithm takes two input variables, an element to flatten and a context used to compact the flattened document.
@default member of
      nodeMap; a JSON object representing the default graph.@id member whose value is set to graphName.@graph member set to an empty array
          (referred to as nodes) to the JSON object which is the
          value of the graphName member of nodeMap.@graph keyword (or its alias)
      at the top-level, even if the context is empty or if there is only one element to
      put in the @graph array. This ensures that the returned
      document has a deterministic structure.This algorithm creates a JSON object nodeMap holding an indexed
    representation of the graphs and nodes
    represented in the passed, expanded document. All nodes that are not
    uniquely identified by an IRI get assigned a (new) blank node identifier.
    The resulting nodeMap will have a member for every graph in the document whose
    value is another object with a member for every node represented in the document.
    The default graph is stored under the @default member, all other graphs are
    stored under their graph name.
The algorithm takes as input an expanded JSON-LD document element and a reference to
    a JSON object nodeMap. Furthermore it has the optional parameters
    active graph (which defaults to @default), an active subject,
    active property, and a reference to a JSON object list. The
    nodeMap must be initialized to a JSON object consisting of a single member
    whose name corresponds with active graph and whose value is an empty JSON object.
@type member, perform for each item the following
      steps:
      @id
          with the value item.@value member, perform the following steps:
      Handling of free-floating values is still being discussed.
@list member of list.@list member, perform
      the following steps:
      @list whose value is initialized to an empty array.@list member as new element and result as list.Handling of free-floating values is still being discussed.
@id member, store its value in id and remove
          the member from element. If id is a blank node identifier, replace it with
          a new blank node identifier.@id whose
          value is set to id.@id whose value is id.@list member of list.@type member, merge each value into the @type
          of active subject in activeGraph. Then remove the @type member
          from element.@annotation member, set the @annotation
          of active subject in activeGraph to its value. If such a member already
          exists in active subject and has a different value, raise a
          CONFLICTING_ANNOTATION error. Otherwise continue and remove the
          @annotation from element.@graph member, recursively invoke this algorithm passing
          the value of the @graph member as new element and id as new
          active subject. Then remove the @graph member from element.This specification describes algorithms to transform JSON-LD documents to an array of RDF quads and vice-versa. Note that many uses of JSON-LD may not require generation of RDF.
The processing algorithms described in this section are provided in order to demonstrate how one might implement a JSON-LD to RDF processor. Conformant implementations are only required to produce the same type and number of quads but are not required to implement the algorithm exactly as described.
This algorithm hasn't been updated yet.
The algorithm below is designed for in-memory implementations with random access to JSON object elements.
A conforming JSON-LD processor implementing RDF conversion must implement a processing algorithm that results in the same set of RDF quads that the following algorithm generates:
The algorithm takes four input variables: a element to be converted, an active subject, active property and graph name. To begin, the active subject, active property and graph name are set to null, and element is set to the result of performing the Expansion Algorithm on the JSON-LD input which is expected to be a a well-formed JSON-LD document as defined in [JSON-LD]. This removes any existing context to allow the given context to be cleanly applied.
@value property:
              @value is a number, set the
                  active object to a typed value using a canonical lexical form
                  of the value as defined in the section Data Round Tripping.
                  Set datatype to the value of the @type property if it exists, otherwise
                  either xsd:integer or xsd:double, depending
                  on if the value contains a fractional and/or an exponential component.@value is true or false,
                  set the active object to a typed value created from the
                  canonical lexical form of the value. Set datatype to the value of the @type
                  property if it exists, otherwise xsd:boolean.@type property, set the
                  active object to a typed value.
                @language property, set the
                  active object to a language-tagged string.
                xsd:string as the datatype.
                @list property the value must be an array.
              Process its value as a list as described in List Conversion using
              the return value as the active object
            @id property,
              the value must be a string, set the active subject to the previously
              expanded value (either a blank node or an IRI).@id property, set the active
              subject to newly generated blank node.@type, set the active property
                  to rdf:type.
                @graph,
                  process value algorithm recursively, using active subject as graph name
                  and null values for active subject and active property and then
                  proceed to next property.rdf:type so set the active object to an IRI.List Conversion is the process of taking an array of values and adding them to a newly
        created RDF Collection (see
        [RDF-SCHEMA]) by linking each element of the list using rdf:first and rdf:next,
        terminating the list with rdf:nil using the following sequence:
The algorithm is invoked with an array array, the active property and returns a value to be used as an active object in the calling location.
This algorithm hasn't been updated yet.
rdf:nil.
        rdf:first as the active property.
              rdf:nil.rdf:rest and rest blank node.In some cases, data exists natively in the form of triples or or quads; for example, if the data was originally represented in an RDF graph or triple/quad store. This algorithm is designed to simply translate an array of quads into a JSON-LD document.
When expanding typed values having a datatype of xsd:string,
        the @type must not be set to xsd:string and the resulting value
        must have only a @value property.
The conversion algorithm takes a single parameter input in the form of an array of Quad representations.
This algorithm hasn't been updated yet.
rdf:first,
              use the entry in graph.listMap indexed by subject,
              initializing it to a new JSON object if nesessary. Represent
              object in expanded form, as described in
              Value Expansion. Add the
              resulting object representation to the entry indexed by
              first, and skip to the next quad.rdf:rest:
              @id and
              name represented in expanded IRI form.@id and
              subject represented in expanded IRI form if necessary.rdf:type, object is not a JSON-LD value, and the
              useRdfType
              option is not present or false:
              @type, creating an entry in value if necessary.useNativeTypes
              option is set to true:
              xsd:boolean, the
                      converted value is true if the literal
                      matches the value true or false if
                      the literal matches the value false.xsd:integer or
                      xsd:double, try to convert the literal to a
                      JSON number. If the conversion is successful,
                      store the result in converted value, otherwise
                      set converted value to value.rdf:nil:
              @list representation to the array value for
                  key, creating an entry in value if necessary.@id in value.@list initialized to a new array
                  containing the value of first from entry.@graph in entry containing the ordered entries
              from graphs[subject].nodes.When converting JSON-LD to RDF JSON-native types such as numbers and booleans are automatically coerced to xsd:integer, xsd:double, or xsd:boolean. Implementers must ensure that the result is in canonical lexical form. A canonical lexical form is a set of literals from among the valid set of literals for a datatype such that there is a one-to-one mapping between the canonical lexical form and a value in the value space as defined in [XMLSCHEMA11-2]. In other words, every value must be converted to a deterministic string representation.
The canonical lexical form of an integer, i.e., a number without fractions
        or a number coerced to xsd:integer, is a finite-length sequence of decimal
        digits (0-9) with an optional leading minus sign; leading zeroes are prohibited.
        To convert the number in JavaScript, implementers can use the following snippet of code:
(value).toFixed(0).toString()
The canonical lexical form of a double, i.e., a number with fractions
        or a number coerced to xsd:double, consists of a mantissa followed by the
        character "E", followed by an exponent. The mantissa must be a decimal number. The exponent
        must be an integer. Leading zeroes and a preceding plus sign (+) are prohibited
        in the exponent. If the exponent is zero, it must be indicated by E0.
        For the mantissa, the preceding optional plus sign is prohibited and the decimal point is
        required. Leading and trailing zeroes are prohibited subject to the following: number
        representations must be normalized such that there is a single digit which is non-zero to the
        left of the decimal point and at least a single digit to the right of the decimal point unless
        the value being represented is zero. The canonical representation for zero is 0.0E0.
        xsd:double's value space is defined by the IEEE double-precision 64-bit
        floating point type [IEEE-754-1985]; in JSON-LD the mantissa is rounded to 15 digits after the
        decimal point.
To convert the number in JavaScript, implementers can use the following snippet of code:
(value).toExponential(15).replace(/(\d)0*e\+?/,'$1E')
When data such as decimals need to be normalized, JSON-LD authors should not use values that are going to undergo automatic conversion. This is due to the lossy nature of xsd:double values. Authors should instead use the expanded object form to set the canonical lexical form directly.
The canonical lexical form of the boolean values true and false
        are the strings true and false.
When JSON-native numbers, are type coerced, lossless data round-tripping can not be guaranted as rounding errors might occur. Additionally, only literals typed as xsd:integer, xsd:double, and xsd:boolean are automatically converted back to their JSON-native counterparts in when converting from RDF.
Some JSON serializers, such as PHP's native implementation in some versions,
        backslash-escape the forward slash character. For example, the value
        http://example.com/ would be serialized as http:\/\/example.com\/.
        This is problematic as other JSON parsers might not understand those escaping characters.
        There is no need to backslash-escape forward slashes in JSON-LD. To aid interoperability
        between JSON-LD processors, a JSON-LD serializer must not backslash-escape forward slashes.
This API provides a clean mechanism that enables developers to convert JSON-LD data into a a variety of output formats that are easier to work with in various programming languages. If a JSON-LD API is provided in a programming environment, the entirety of the following API must be implemented.
The JSON-LD processor interface is the high-level programming structure that developers use to access the JSON-LD transformation methods.
The JSON-LD API signatures are the same across all programming languages. Due
      to the fact that asynchronous programming is uncommon in certain languages, developers may
      implement a processor with a synchronous interface instead. In that case, the callback
      parameter must not be included and the result must be returned as a return value instead.
It is important to highlight that conformant JSON-LD processors must not modify the input parameters.
[Constructor]
interface JsonLdProcessor {
    void expand ((object or object[] or DOMString) input, JsonLdCallback callback, optional JsonLdOptions? options);
    void compact ((object or object[] or DOMString) input, (object or DOMString) context, JsonLdCallback callback, optional JsonLdOptions? options);
    void flatten ((object or object[] or DOMString) input, (object or DOMString)? context, JsonLdCallback callback, optional JsonLdOptions? options);
};compactinput using the
        context according to the steps in the
        Compaction Algorithm.
        
      | Parameter | Type | Nullable | Optional | Description | 
|---|---|---|---|---|
| input | (object or object[] or DOMString) | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects to perform the compaction upon or an IRI referencing the JSON-LD document to compact. | 
| context | (object or DOMString) | ✘ | ✘ | The context to use when compacting the input; either in the
            form of an JSON object or as IRI. | 
| callback |  | ✘ | ✘ | A callback that is called when processing is complete on
            the given input. | 
| options |  | ✔ | ✔ | A set of options to configure the used algorithms such. This allows, e.g.,
            to set the input document's base IRI. This also includes
            the optimize flag, which, if set, will allow processor-specific
            optimization. | 
voidexpandinput according to
        the steps in the Expansion Algorithm.
        
      | Parameter | Type | Nullable | Optional | Description | 
|---|---|---|---|---|
| input | (object or object[] or DOMString) | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects to perform the expansion upon or an IRI referencing the JSON-LD document to expand. | 
| callback |  | ✘ | ✘ | A callback that is called when processing is complete on
            the given input. | 
| options |  | ✔ | ✔ | A set of options to configure the used algorithms such. This allows, e.g., to set the input document's base IRI. | 
voidflatteninput and
        compacts it using the passed context
          according to the steps in the Flattening Algorithm.
        
      | Parameter | Type | Nullable | Optional | Description | 
|---|---|---|---|---|
| input | (object or object[] or DOMString) | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects or an IRI referencing the JSON-LD document to flatten. | 
| context | (object or DOMString) | ✔ | ✘ | The context to use when compacting the flattened input; either
            in the form of an JSON object or as IRI. If
            null is passed, the result will not be compacted but keept
            in expanded form. | 
| callback |  | ✘ | ✘ | A callback that is called when processing is complete on the given
            input. | 
| options |  | ✔ | ✔ | A set of options to configure the used algorithms such. This allows, e.g., to set the input document's base IRI. | 
voidJSON-LD processors utilize callbacks in order to return information in an asynchronous manner to calling applications. This section details the parameters sent to those callbacks.
The JsonLdCallback is called when processing of an API method
        of JsonLdProcessor has been completed successfully or been
        terminated by an error.
callback JsonLdCallback = void (JsonLdProcessingError error, object or object[] document);JsonLdCallback Parameterserror of type JsonLdProcessingErrornull, then no error occurred. If
          the value is non-null, a processing error occurred
          and the details will be contained within the error
          object.document of type array of object or objectThis section describes datatype definitions used within the JSON-LD API.
The JsonLdOptions type is used to pass various options to the JsonLdProcessor methods.
dictionary JsonLdOptions {
    DOMString           base;
    object or DOMString expandContext = null;
    boolean             compactArrays = true;
    boolean             optimize = false;
    boolean             useRdfType = false;
    boolean             useNativeTypes = true;
};JsonLdOptions Membersbase of type DOMStringcompactArrays of type boolean, defaulting to truetrue, the JSON-LD processor replaces arrays with just
          one element with that element during compaction. If set to false,
          all arrays will remain arrays even if they have just one element.
        expandContext of type object or DOMString, defaulting to nulloptimize of type boolean, defaulting to falsetrue, the JSON-LD processor is allowed to
          optimize the output of the Compaction Algorithm
          to produce even compacter representations. The algorithm for compaction
          optimization is beyond the scope of this specification and thus
          not defined. Consequently, different implementations may implement
          different optimization algorithms.
        useNativeTypes of type boolean, defaulting to truetrue, the JSON-LD processor will try to convert
          typed values to JSON native types instead of using the
          expanded object form when converting from RDF.
          xsd:boolean values will be converted to true or false.
          xsd:integer and xsd:double values will be
          converted to
          JSON numbers.
        useRdfType of type boolean, defaulting to falsetrue, the JSON-LD processor will use the
          expanded rdf:type IRI as the property instead of
          @type when converting from RDF.
        Developers should note that the details of error handling are being actively debated.
The JsonLdProcessingError type is used to report errors to a
        JsonLdCallback.
dictionary JsonLdProcessingError {
    JsonLdErrorCode code;
    DOMString?      message;
};JsonLdProcessingError Memberscode of type JsonLdErrorCodemessage of type DOMString, nullableThe JsonLdErrorCode represent the collection of valid JSON-LD error codes.
enum JsonLdErrorCode {
    "INVALID_SYNTAX",
    "LOAD_ERROR",
    "LIST_OF_LISTS_DETECTED"
};| Enumeration description | |
|---|---|
INVALID_SYNTAX | A violation of the grammar as defined by the JSON-LD syntax specification [JSON-LD] was detected. | 
LOAD_ERROR | There was a problem encountered loading a remote context. | 
LIST_OF_LISTS_DETECTED | A list of lists was detected. List of lists are not supported in this version of JSON-LD due to the algorithmic complexity associated with conversion to RDF. | 
A large amount of thanks goes out to the JSON-LD Community Group participants who worked through many of the technical issues on the mailing list and the weekly telecons - of special mention are Niklas Lindström, François Daoust, Lin Clark, and Zdenko 'Denny' Vrandečić. The editors would like to thank Mark Birbeck, who provided a great deal of the initial push behind the JSON-LD work via his work on RDFj. The work of Dave Lehn and Mike Johnson are appreciated for reviewing, and performing several implementations of the specification. Ian Davis is thanked for his work on RDF/JSON. Thanks also to Nathan Rixham, Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant, Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Josh Mandel, Eric Prud'hommeaux, David Wood, Guus Schreiber, Pat Hayes, Sandro Hawke, and Richard Cyganiak or their input on the specification.