JSON-LD 1.1 Processing Algorithms and API

W3C Working Draft

This version:
https://www.w3.org/TR/2019/WD-json-ld11-api-20190802/
Latest published version:
https://www.w3.org/TR/json-ld11-api/
Latest editor's draft:
https://w3c.github.io/json-ld-api/
Test suite:
https://w3c.github.io/json-ld-api/tests/
Previous version:
https://www.w3.org/TR/2019/WD-json-ld11-api-20190713/
Latest Recommendation:
https://www.w3.org/TR/2014/REC-json-ld-api-20140116/
Editor:
Gregg Kellogg (v1.0 and v1.1)
Former editors:
Markus Lanthaler (Graz University of Technology) (v1.0)
Manu Sporny (Digital Bazaar) (v1.0)
Authors:
Dave Longley (Digital Bazaar) (v1.0)
Gregg Kellogg (v1.0 and v1.1)
Markus Lanthaler (Graz University of Technology) (v1.0)
Manu Sporny (Digital Bazaar) (v1.0)
Niklas Lindström (v1.0)
Participate:
GitHub w3c/json-ld-api
File a bug
Commit history
Pull requests

Abstract

This specification defines a set of algorithms for programmatic transformations of JSON-LD documents. Restructuring data according to the defined transformations often dramatically simplifies its usage. Furthermore, this document proposes an Application Programming Interface (API) for developers implementing the specified algorithms.

Status of This Document

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 https://www.w3.org/TR/.

This document has been developed by the JSON-LD Working Group and was derived from the JSON-LD Community Group's Final Report.

There is a live JSON-LD playground that is capable of demonstrating the features described in this document.

This document was published by the JSON-LD Working Group as a Working Draft. This document is intended to become a W3C Recommendation.

GitHub Issues are preferred for discussion of this specification. Alternatively, you can send comments to our mailing list. Please send them to public-json-ld-wg@w3.org (archives).

Publication as a Working 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 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 document is governed by the 1 March 2019 W3C Process Document.

Set of Documents

This document is one of three JSON-LD 1.1 Recommendations produced by the JSON-LD Working Group:

1. Introduction

This section is non-normative.

This document is a detailed specification of the JSON-LD processing algorithms. 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 [RFC8259]. You must also understand the JSON-LD syntax defined in the JSON-LD 1.1 Syntax specification [JSON-LD11], 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 [ECMASCRIPT] and WebIDL [WEBIDL]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [RDF11-CONCEPTS].

1.1 Contributing

This section is non-normative.

There are a number of ways that one may participate in the development of this specification:

1.2 Typographical conventions

This section is non-normative.

The following typographic conventions are used in this specification:

markup
Markup (elements, attributes, properties), machine processable values (string, characters, media types), property name, or a file name is in red-orange monospace font.
variable
A variable in pseudo-code or in an algorithm description is in italics.
definition
A definition of a term, to be used elsewhere in this or other specifications, is in bold and italics.
definition reference
A reference to a definition in this document is underlined and is also an active link to the definition itself.
markup definition reference
A references to a definition in this document, when the reference itself is also a markup, is underlined, red-orange monospace font, and is also an active link to the definition itself.
external definition reference
A reference to a definition in another document is underlined, in italics, and is also an active link to the definition itself.
markup external definition reference
A reference to a definition in another document, when the reference itself is also a markup, is underlined, in italics red-orange monospace font, and is also an active link to the definition itself.
hyperlink
A hyperlink is underlined and in blue.
[reference]
A document reference (normative or informative) is enclosed in square brackets and links to the references section.
Changes from Recommendation
Sections or phrases changed from the previous Recommendation are highlighted.
Note

Notes are in light green boxes with a green left border and with a "Note" header in green. Notes are always informative.

  Examples are in light khaki boxes, with khaki left border,
  and with a numbered "Example" header in khaki.
  Examples are always informative. The content of the example is in monospace font and may be syntax colored.

  Examples may have tabbed navigation buttons
  to show the results of transforming an example into other representations.

1.3 Terminology

This document uses the following terms as defined in JSON [RFC8259]. Refer to the JSON Grammar section in [RFC8259] for formal definitions.

Terms imported from Other Specifications

Terms imported from ECMAScript Language Specification [ECMASCRIPT], The JavaScript Object Notation (JSON) Data Interchange Format [RFC8259], Infra Standard [INFRA], and Web IDL [WEBIDL]

array
In the JSON serialization, an array structure is represented as square brackets surrounding zero or more values. Values are separated by commas. In the internal representation, a list (also called an array) is an ordered collection of zero or more values. While JSON-LD uses the same array representation as JSON, the collection is unordered by default. While order is preserved in regular JSON arrays, it is not in regular JSON-LD arrays unless specifically defined (see Sets and Lists in the JSON-LD Syntax specification [JSON-LD11]).
boolean
The values true and false that are used to express one of two possible states.
JSON object
In the JSON serialization, an object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string. A single colon comes after each name, separating the name from the value. A single comma separates a value from a following name. In JSON-LD the names in an object MUST be unique.

In the internal representation a JSON object is described as a map (see [INFRA]), composed of entries with key/value pairs.

In the Application Programming Interface, a map is described using a [WEBIDL] dictionary.

null
The use of the null value within JSON-LD is used to ignore or reset values. A map entry in the @context where the value, or the @id of the value, is null, explicitly decouples a term's association with an IRI. A map entry in the body of a JSON-LD document whose value is null has the same meaning as if the map entry was not defined. If @value, @list, or @set is set to null in expanded form, then the entire JSON object is ignored.
number
In the JSON serialization, a number is similar to that used in most programming languages, except that the octal and hexadecimal formats are not used and that leading zeros are not allowed. In the internal representation, a number is equivalent to either a long or double, depending on if the number has a non-zero fractional part (see [WEBIDL]).
scalar
A scalar is either a string, number, true, or false.
string
A string is a sequence of zero or more Unicode (UTF-8) characters, wrapped in double quotes, using backslash escapes (if necessary). A character is represented as a single character string.

Terms imported from Internationalized Resource Identifiers (IRIs) [RFC3987]

absolute IRI
The absolute form of an IRI containing a scheme along with a path and optional query and fragment segments.
IRI reference
Denotes the common usage of an Internationalized Resource Identifier. An IRI reference may be absolute or relative. However, the "IRI" that results from such a reference only includes absolute IRIs; any relative IRI references are resolved to their absolute form.
relative IRI
A relative IRI is an IRI that is relative to some other absolute IRI, typically the base IRI of the document. Note that properties, values of @type, and values of terms defined to be vocabulary relative are resolved relative to the vocabulary mapping, not the base IRI.

Terms imported from RDF 1.1 Concepts and Abstract Syntax [RDF11-CONCEPTS], RDF Schema 1.1 [RDF-SCHEMA], and Linked Data Design Issues [LINKED-DATA]

base IRI
The base IRI is an absolute IRI established in the context, or is based on the JSON-LD document location. The base IRI is used to turn relative IRIs into absolute IRIs.
blank node
A node in a graph that is neither an IRI, nor a JSON-LD value, nor a list. A blank node does not contain a de-referenceable identifier because it is either ephemeral in nature or does not contain information that needs to be linked to from outside of the linked data graph. A blank node is assigned an identifier starting with the prefix _:.
blank node identifier
A blank node identifier is a string that can be used as an identifier for a blank node within the scope of a JSON-LD document. Blank node identifiers begin with _:.
dataset
A dataset representing a collection of RDF graphs including exactly one default graph and zero or more named graphs.
datatype IRI
A datatype IRI is an IRI identifying a datatype that determines how the lexical form maps to a literal value.
default graph
The default graph is an RDF graph having no name, which MAY be empty.
graph name
The IRI or blank node identifying a named graph.
language-tagged string
A language-tagged string consists of a string and a non-empty language tag as defined by [BCP47]. The language tag MUST be well-formed according to section 2.2.9 Classes of Conformance of [BCP47], and is normalized to lowercase.
Linked Data
A set of documents, each containing a representation of a linked data graph.
list
A list is an ordered sequence of IRIs, blank nodes, and literals.
literal
An object expressed as a value such as a string or number. Implicitlly or explicitly includes a datatype IRI and, if the datatype is xsd:string, an optional language tag.
named graph
A named graph is a linked data graph that is identified by an IRI or blank node.
node
A node in an RDF graph, made up of the set of subjects and objects of triples in the graph.
object
An object is a node in a linked data graph with at least one incoming edge.
property
The name of a directed-arc in a linked data graph. Every property is directional and is labeled with an IRI or a blank node identifier. Whenever possible, a property should be labeled with an IRI.
(Feature at Risk) Issue
The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD.
Also, see predicate in [RDF11-CONCEPTS].
RDF graph
A labeled directed graph, i.e., a set of nodes connected by directed-arcs.
resource
A resource donoted by an IRI or literal representing something in the world ( the "universe of discourse").
subject
A subject is a node in a linked data graph with at least one outgoing edge, related to an object node through a property.
triple
A component of an RDF graph including a subject, predicate, and object, which represents a node-arc-node segment of an RDF graph.

JSON-LD Specific Term Definitions

active context
A context that is used to resolve terms while the processing algorithm is running.
compact IRI
A compact IRI has the form of prefix:suffix and is used as a way of expressing an IRI without needing to define separate term definitions for each IRI contained within a common vocabulary identified by prefix.
context
A set of rules for interpreting a JSON-LD document as specified in the The Context section of the JSON-LD Syntax specification [JSON-LD11].
default language
The default language is set in the context using the @language key whose value MUST be a string representing a [BCP47] language code or null.
default object
A default object is a map that has a @default key.
embedded context
An embedded context is a context which appears as part of a node object, value object, graph object, list object, set object, or as part of nested properties, or in an expanded term definition using the @context entry. Its value may be a map for a context definition, as an IRI, or as an array combining either of the above.
expanded term definition
An expanded term definition is a term definition where the value is a map containing one or more keyword keys to define the associated absolute IRI, if this is a reverse property, the type associated with string values, and a container mapping.
frame
A JSON-LD document, which describes the form for transforming another JSON-LD document using matching and embedding rules. A frame document allows additional keywords and certain map entries to describe the matching and transforming process.
frame object
A frame object is a map element within a frame which represents a specific portion of the frame matching either a node object or a value object in the input.
graph object
A graph object represents a named graph as the value of a map entry within a node object. When expanded, a graph object MUST have an @graph entry, and MAY also have @id, and @index entries. A simple graph object is a graph object which does not have an @id entry. Note that node objects may have a @graph entry, but are not considered graph objects if they include any other entries. A top-level object consisting of @graph is also not a graph object. Note that a node object may also represent a named graph it it includes other properties.
id map
An id map is a map value of a term defined with @container set to @id. The values of the id map MUST be node objects, and its keys are interpreted as IRIs representing the @id of the associated node object. If a value in the id map contains a key expanding to @id, it's value MUST be equivalent to the referencing key in the id map.
implicitly named graph
A named graph created from the value of a map entry having an expanded term definition where @container is set to @graph.
included block
An included block is an entry in a node object where the key is either @included or an alias of @included and the value is one ore more node objects.
index map
An index map is a map value of a term defined with @container set to @index, whose values MUST be any of the following types: string, number, true, false, null, node object, value object, list object, set object, or an array of zero or more of the above possibilities.
JSON literal
A JSON literal is a literal where the associated IRI is rdf:JSON. In the value object representation, the value of @type is @json. JSON literals represent values which are valid JSON [RFC8259]. See JSON datatype in [JSON-LD11].
JSON-LD document
A JSON-LD document is a serialization of a collection of graphs and comprises exactly one default graph and zero or more named graphs.
JSON-LD internal representation
The JSON-LD internal representation is the result of transforming a JSON syntactic structure into the core data structures suitable for direct processing: arrays, maps, strings, numbers, booleans, and null.
JSON-LD Processor
A JSON-LD Processor is a system which can perform the algorithms defined in [JSON-LD11-API].
JSON-LD value
A JSON-LD value is a string, a number, true or false, a typed value, or a language-tagged string.
keyword
A string that is specific to JSON-LD, specified in the JSON-LD Syntax specification [JSON-LD11] in the section titled Syntax Tokens and Keywords.
language map
An language map is a map value of a term defined with @container set to @language, whose keys MUST be strings representing [BCP47] language codes and the values MUST be any of the following types: null, string, or an array of zero or more of the above possibilities.
list object
A list object is a map that has a @list key. It may also have an @index key, but no other entries.
local context
A context that is specified with a map, specified via the @context keyword.
nested property
A nested property is a key in a node object whose value is a map containing entries which are treated as if they were values of the node object. The nested property itself is semantically meaningless and used only to create a sub-structure within a node object.
node object
A node object represents zero or more properties of a node in the graph serialized by the JSON-LD document. A map is a node object if it exists outside of the JSON-LD context and:
  • it does not contain the @value, @list, or @set keywords, or
  • it is not the top-most map in the JSON-LD document consisting of no other entries than @graph and @context.
The entries of a node object whose keys are not keywords are also called properties of the node object.
node reference
A node object used to reference a node having only the @id key.
prefix
A prefix is the first component of a compact IRI which comes from a term that maps to a string that, when prepended to the suffix of the compact IRI, results in an absolute IRI.
processing mode
The processing mode defines how a JSON-LD document is processed. By default, all documents are assumed to be conformant with JSON-LD 1.0 [JSON-LD]. By defining a different version using the @version entry in a context, or via explicit API option, other processing modes can be accessed. This specification defines extensions for the json-ld-1.1 processing mode.
scoped context
A scoped context is part of an expanded term definition using the @context entry. It has the same form as an embedded context. When the term is used as a type, it defines a type-scoped context, when used as a property it defines a property-scoped context.
set object
A set object is a map that has an @set entry. It may also have an @index key, but no other entries.
term
A term is a short word defined in a context that MAY be expanded to an IRI.
term definition
A term definition is an entry in a context, where the key defines a term which may be used within a map as a key, type, or elsewhere that a string is interpreted as a vocabulary item. Its value is either a string (simple term definition), expanding to an absolute IRI, or an expanded term definition.
type map
A type map is a map value of a term defined with @container set to @type, whose keys are interpreted as IRIs representing the @type of the associated node object; the value MUST be a node object, or array of node objects. If the value contains a term expanding to @type, it's values are merged with the map value when expanding.
typed value
A typed value consists of a value, which is a string, and a type, which is an IRI.
value object
A value object is a map that has an @value entry.
vocabulary mapping
The vocabulary mapping is set in the context using the @vocab key whose value MUST be an IRI or null.

1.3.1 Algorithm Terms

The Following terms are used within specific algorithms.

active graph
The name of the currently active graph that the processor should use when processing.
active object
The currently active object that the processor should use when processing.
active property
The currently active property or keyword that the processor should use when processing. The active property is represented in the original lexical form, which is used for finding coercion mappings in the active context.
active subject
The currently active subject that the processor should use when processing.
explicit inclusion flag
A flag specifying that for properties to be included in the output, they MUST be explicitly declared in the matching frame.
framing state
A map containing values for the object embed flag, the require all flag, the explicit inclusion flag, and the omit default flag.
input frame
The initial Frame provided to the framing algorithm.
JSON-LD input
The JSON-LD data structure that is provided as input to the algorithm.
JSON-LD output
The JSON-LD data structure that is produced as output by the algorithm.
map of flattened subjects
A map of subjects that is the result of the Node Map Generation algorithm.
object embed flag
A flag specifying that node objects should be directly embedded in the output, instead of being referred to by their IRI.
omit default flag
A flag specifying that properties that are missing from the JSON-LD input, but present in the input frame, should be omitted from the output.
omit graph flag
A flag that determines if framing output is always contained within a @graph entry, or only if required to represent multiple node objects.
processor state
The processor state, which includes the active context, active subject, and active property. The processor state is managed as a stack with elements from the previous processor state copied into a new processor state when entering a new JSON object.
require all flag
A flag specifying that all properties present in the input frame MUST either have a default value or be present in the JSON-LD input for the frame to match.

1.4 Example Conventions

This section is non-normative.

Note that in the examples used in this document, output is of necessity shown in serialized form as JSON. While the algorithms describe operations on the JSON-LD internal representation, when they as displayed as examples, the JSON serialization is used. In particular, the internal representation use of maps are represented using JSON objects.

Example 2: Sample JSON-LD 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": "Dave Longley"
    }
  ]
}

In the internal representation, the example above would be of a map containing @context, @id, name, and knows entries, with either maps, strings, or arrays of maps or strings values. In the JSON serialization, JSON objects are used for maps, while arrays and strings are serialized using a convention common to many programming languages.

2. Features

This section is non-normative.

The JSON-LD 1.1 Syntax specification [JSON-LD11] defines a syntax to express Linked Data in JSON. Because there is more than one way to express Linked Data using this syntax, it is often useful to be able to transform JSON-LD documents so that they may be more easily consumed by specific applications.

To allow these algorithms to be adapted for syntaxes other than JSON, the algorithms operate on the JSON-LD internal representation, which uses the generic concepts of arrays, maps, strings, numbers, booleans, and null to describe the data represented by a JSON document. Algorithms act on this internal representation with API entry points responsible for transforming between the concrete and internal representations.

JSON-LD uses contexts to allow Linked Data to be expressed in a way that is specifically tailored to a particular person or application. By providing a context, JSON data can be expressed in a way that is a natural fit for a particular person or application whilst also indicating how the data should be understood at a global scale. In order for people or applications to share data that was created using a context that is different from their own, a JSON-LD processor must be able to transform a document from one context to another. Instead of requiring JSON-LD processors to write specific code for every imaginable context switching scenario, it is much easier to specify a single algorithm that can remove any context. Similarly, another algorithm can be specified to subsequently apply any context. These two algorithms represent the most basic transformations of JSON-LD documents. They are referred to as expansion and compaction, respectively.

JSON-LD 1.1 introduces new features that are compatible with JSON-LD 1.0 [JSON-LD], but if processed by a JSON-LD 1.0 processor may produce different results. In order to detect this JSON-LD 1.1 requires that the processing mode be explicitly set to json-ld-1.1, either through the processingMode API option, or using the @version map entry within a context.

There are four major types of transformation that are discussed in this document: expansion, compaction, flattening, and RDF serialization/deserialization.

2.1 Expansion

This section is non-normative.

The algorithm that removes context is called expansion. Before performing any other transformations on a JSON-LD document, it is easiest to remove any context from it and to make data structures more regular.

To get an idea of how context and data structuring affects the same data, here is an example of JSON-LD that uses only terms and is fairly compact:

The next input example uses one IRI to express a property and an array to encapsulate another, but leaves the rest of the information untouched.

Note that both inputs are valid JSON-LD and both represent the same information. The difference is in their context information and in the data structures used. A JSON-LD processor can remove context and ensure that the data is more regular by employing expansion.

Expansion has two important goals: removing any contextual information from the document, and ensuring all values are represented in a regular form. These goals are accomplished by expanding all entry keys to absolute IRIs and by expressing all values in arrays in expanded form. Expanded form is the most verbose and regular way of expressing of values in JSON-LD; all contextual information from the document is instead stored locally with each value. Running the Expansion algorithm (expand()) operation) against the above examples results in the following output:

Example 5: Expanded JSON-LD document using an IRI
[
  {
    "@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/" }
    ]
  }
]

The example above is the JSON-LD serialization of the output of the expansion algorithm, where the algorithm's use of maps are replaced with JSON objects.

Note that in the output above all context definitions have been removed, all terms and compact IRIs have been expanded to absolute IRIs, and all JSON-LD values are expressed in arrays in expanded form. While the output is more verbose and difficult for a human to read, it establishes a baseline that makes JSON-LD processing easier because of its very regular structure.

2.2 Compaction

This section is non-normative.

While expansion removes context from a given input, compaction's primary function is to perform the opposite operation: to express a given input according to a particular context. Compaction applies a context that specifically tailors the way information is expressed for a particular person or application. This simplifies applications that consume JSON or JSON-LD by expressing the data in application-specific terms, and it makes the data easier to read by humans.

Compaction uses a developer-supplied context to shorten IRIs to terms or compact IRIs and JSON-LD values expressed in expanded form to simple values such as strings or numbers.

For example, assume the following expanded JSON-LD input document:

Example 6: Expanded sample 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:

Example 7: 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 (compact()) operation) given the context supplied above against the JSON-LD input document provided above would result in the following output:

The example above is the JSON-LD serialization of the output of the compaction algorithm, where the algorithm's use of maps are replaced with JSON objects.

Note that all IRIs have been compacted to terms as specified in the context, which has been injected into the output. While compacted output is useful to humans, it is also 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 also have been mapped to any other term provided by the developer.

2.3 Flattening

This section is non-normative.

While expansion ensures that a document is in a uniform structure, flattening goes a step further to ensure that the shape of the data is deterministic. In expanded documents, the properties of a single node may be spread across a number of different maps. By flattening a document, all properties of a node are collected in a single map and all blank nodes are labeled with a blank node identifier. This may drastically simplify the code required to process JSON-LD data in certain applications.

For example, assume the following JSON-LD input document:

Example 9: JSON-LD document in compact form
{
  "@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": "Dave Longley"}
  ]
}

Running the Flattening Algorithm (flatten()) operation) with a context set to null to prevent compaction returns the following document:

The example above is the JSON-LD serialization of the output of the flattening algorithm, where the algorithm's use of maps are replaced with JSON objects.

Note how in the output above all properties of a node are collected in a single map and how the blank node representing "Dave Longley" has been assigned the blank node identifier _:b0.

To make it easier for humans to read or for certain applications to process it, 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:

Please note that the result of flattening and compacting a document is always a map, (represented as a JSON object when serialized), which contains an @graph entry that represents the default graph.

2.4 RDF Serialization/Deserialization

This section is non-normative.

JSON-LD can be used to serialize RDF data as described in [RDF11-CONCEPTS]. This ensures that data can be round-tripped to and from any RDF syntax without any loss in fidelity.

For example, assume the following RDF input serialized in Turtle [TURTLE]:

Example 12: Sample Turtle document
<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 Serialize RDF as JSON-LD Algorithm a developer could transform this document into expanded JSON-LD:

Example 13: Sample Turtle document converted to 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/" }
    ]
  }
]

The example above is the JSON-LD serialization of the output of the Serialize RDF as JSON-LD Algorithm, where the algorithm's use of maps are replaced with JSON objects.

Note that the output above could easily be compacted using the technique outlined in the previous section. It is also possible to deserialize the JSON-LD document back to RDF using the Deserialize JSON-LD to RDF Algorithm.

3. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, MUST NOT, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

There are two classes of products that can claim conformance to this specification: JSON-LD Processors, and RDF Serializers/Deserializers.

A conforming JSON-LD Processor is a system which can perform the Expansion, Compaction, and Flattening operations in a manner consistent with the algorithms defined in this specification.

JSON-LD Processors MUST NOT attempt to correct malformed IRIs or language tags; however, they MAY issue validation warnings. IRIs are not modified other than conversion between relative and absolute IRIs.

A conforming RDF Serializer/Deserializer is a system that can deserialize JSON-LD to RDF and serialize RDF as JSON-LD as defined in this specification.

The algorithms in this specification are generally written with more concern for clarity than efficiency. Thus, JSON-LD 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.

In algorithm steps that describe operations on keywords, those steps also apply to keyword aliases.

Note

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 specification makes use of the following namespace prefixes:

Prefix IRI
rdf http://www.w3.org/1999/02/22-rdf-syntax-ns#
xsd http://www.w3.org/2001/XMLSchema#

3.1 Processor Levels

JSON-LD mostly uses the JSON syntax [RFC8259] along with various micro-syntaxes based on XML Schema datatypes [XMLSCHEMA11-2]. However, it has become increasingly common to include JSON within a script element within an HTML document [HTML], as described in § 9. HTML Content Algorithms. As not all processors operate in an environment which can include HTML, this specification describes various categories of JSON-LD processors.

A pure JSON Processor only requires the use of a JSON processor and is restricted to processing documents retrieved with a JSON content type (e.g., application/ld+json or other JSON type).

A full Processor is capable of processing JSON-LD embedded in HTML, in addition to the capabilities of a pure JSON Processor.

3.1.1 Additional Processor Levels

This section is non-normative.

In addition to the normatively defined processor levels, an additional processor level is defined for reference.

A event-based JSON Processor processes a stream of characters expecting an event after each syntactic element is encountered. Such processors are sensitive to the order of the members of JSON objects, which can have a performance impact if the members of JSON objects are encountered in an unexpected order. An event-based JSON Processor may process JSON-LD embedded in HTML.

Note

An event-based JSON Processor may be sensitive to processing certain keywords in order, including @context, @id, and @type.

4. Context Processing Algorithms

4.1 Context Processing Algorithm

When processing a JSON-LD data structure, each processing rule is applied using information provided by the active context. This section describes how to produce an active context.

The active context contains the active term definitions which specify how keys and values have to be interpreted as well as the current base IRI, the vocabulary mapping, the default language, and an optional previous context, used when a non-propagated context is defined. Each term definition consists of:

A term definition can not only be used to map a term to an IRI, but also to map a term to a keyword, in which case it is referred to as a keyword alias.

When processing, active context is initialized without any term definitions, vocabulary mapping, or default language. If a local context is encountered during processing, a new active context is created by cloning the existing active context. Then the information from the local context is merged into the new active context. Given that local contexts may contain references to remote contexts, this includes their retrieval.

4.1.1 Overview

This section is non-normative.

First we prepare a new active context result by cloning the current active context. Then we normalize the form of the original local context to an array. Local contexts may be in the form of a map, a string, or an array containing a combination of the two. Finally we process each context contained in the local context array as follows.

Unless specified using processingMode API option, the processing mode is set using the @version entry in a local context and affects the behavior of algorithms including expansion and compaction.

If context is a string, it represents a reference to a remote context. We dereference the remote context and replace context with the value of the @context entry of the top-level object in the retrieved JSON-LD document. If the result is an HTML document, we attempt to extract JSON-LD from the first script element of type application/ld+json;profile=http://www.w3.org/ns/json-ld#context or application/ld+json, if no context profile exists. If there's no such entry, an invalid remote context has been detected. Otherwise, we process context by recursively using this algorithm ensuring that there is no cyclical reference.

If context is a map, it is a context definition. We first update the base IRI, the vocabulary mapping, processing mode, and the default language by processing three specific keywords: @base, @vocab, @version, and @language. These are handled before any other entries in the local context because they affect how the other entries are processed. If context contains @import, it is retrieved and is reverse-merged into the containing context, allowing JSON-LD 1.0 contexts to be uplifed to JSON-LD 1.1. Please note that @base is ignored when processing remote contexts.

If context is not to be propagated, a reference to the previous context is retained so that it may be rolled back when a new node object is entered. By default, all contexts are propagated, other than type-scoped contexts.

Then, for every other entry in local context, we update the term definition in result. Since term definitions in a local context may themselves contain terms or compact IRIs, we may need to recurse. When doing so, we must ensure that there is no cyclical dependency, which is an error. After we have processed any term definition dependencies, we update the current term definition, which may be a keyword alias.

Finally, we return result as the new active context.

4.1.2 Algorithm

This algorithm specifies how a new active context is updated with a local context. The algorithm takes two required and three optional input variables. The required inputs are an active context and a local context. The optional inputs are an array remote contexts, defaulting to a new empty array, which is used to detect cyclical context inclusions, override protected, defaulting to false, which is used to allow changes to protected terms, and propagate, defaulting to true to mark term definitions associated with non-propagated contexts..

  1. Initialize result to the result of cloning active context.
  2. If local context is an object containing the member @propagate, its value MUST be boolean true or false, set propagate to that value.
  3. If propagate is false, and result does not have a previous context, set previous context in result to active context.
  4. If local context is not an array, set it to an array containing only local context.
  5. For each item context in local context:
    1. If context is null:
      1. If override protected is false and active context contains any protected term definitions, an invalid context nullification has been detected and processing is aborted.
      2. Otherwise, set result to a newly-initialized active context, setting previous context in result to the previous value of result if propagate is false. Continue with the next context. In JSON-LD 1.0, the base IRI was given a default value here; this is now described conditionally in § 10. The Application Programming Interface.
    2. If context is a string,
      1. Set context to the result of resolving value against the base IRI which is established as specified in section 5.1 Establishing a Base URI of [RFC3986]. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization 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].
      2. If the number of entries in the remote contexts array exceeds a processor defined limit, a context overflow error has been detected and processing is aborted; otherwise, add context to remote contexts.
      3. If context was previously dereferenced, then the processor MUST NOT do a further dereference, and context is set to the previously established internal representation.
      4. Otherwise, dereference context using the LoadDocumentCallback, passing context for url, and http://www.w3.org/ns/json-ld#context for profile
      5. If context cannot be dereferenced, or cannot be transformed into the internal representation, a loading remote context failed error has been detected and processing is aborted. If the dereferenced document has no top-level map with an @context entry, an invalid remote context has been detected and processing is aborted; otherwise, set context to the value of that entry.
      6. Set result to the result of recursively calling this algorithm, passing result for active context, context for local context, and a copy of remote contexts.
      7. Continue with the next context.
    3. If context is not a map, an invalid local context error has been detected and processing is aborted.
    4. Otherwise, context is a context definition.
    5. If context has an @version entry:
      1. If the associated value is not 1.1, an invalid @version value has been detected, and processing is aborted.
      2. If processing mode is set to json-ld-1.0, a processing mode conflict error has been detected and processing is aborted.
      3. Set processing mode, to json-ld-1.1, if not already set.
    6. If context has an @import entry:
      1. If processing mode is json-ld-1.0, an invalid context entry error has been detected and processing is aborted.
      2. Otherwise, if its value is not a string, an invalid @import value error has been detected and processing is aborted.
      3. Set import to the result of resolving the value of @import against the base IRI which is established as specified in section 5.1 Establishing a Base URI of [RFC3986]. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization 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].
      4. Dereference import using the LoadDocumentCallback, passing import for url, and http://www.w3.org/ns/json-ld#context for profile
      5. If import cannot be dereferenced, or cannot be transformed into the internal representation, a loading remote context failed error has been detected and processing is aborted.
      6. If the dereferenced document has no top-level map with an @context entry, or if the value of @context is not a context definition (i.e., it is not an map), an invalid remote context has been detected and processing is aborted; otherwise, set import context to the value of that entry.
      7. If import context has a @import entry, an invalid context entry error has been detected and processing is aborted.
      8. Set context to the result of merging context into import context, replacing common entries with those from context.
    7. If context has an @base entry and remote contexts is empty, i.e., the currently being processed context is not a remote context:
      1. Initialize value to the value associated with the @base entry.
      2. If value is null, remove the base IRI of result.
      3. Otherwise, if value is an absolute IRI, the base IRI of result is set to value.
      4. Otherwise, if value is a relative IRI and the base IRI of result is not null, set the base IRI of result to the result of resolving value against the current base IRI of result.
      5. Otherwise, an invalid base IRI error has been detected and processing is aborted.
    8. If context has an @vocab entry:
      1. Initialize value to the value associated with the @vocab entry.
      2. If value is null, remove any vocabulary mapping from result.
      3. Otherwise, if value is an IRI or blank node identifier, the vocabulary mapping of result is set to the result of using the IRI Expansion algorithm, passing result as the active context, value, true for vocab, and true for document relative. . If it is not an IRI, or a blank node identifier, an invalid vocab mapping error has been detected and processing is aborted.
        (Feature at Risk) Issue
        The use of blank node identifiers to value for @vocab is obsolete, and may be removed in a future version of JSON-LD.
    9. If context has an @language entry:
      1. Initialize value to the value associated with the @language entry.
      2. If value is null, remove any default language from result.
      3. Otherwise, if value is string, the default language of result is set to lowercased value. If it is not a string, an invalid default language error has been detected and processing is aborted.
    10. If context has an @propagate entry:
      1. If processing mode is json-ld-1.0, an invalid context entry error has been detected and processing is aborted.
      2. Otherwise, if its value is not boolean true or false, an invalid @propagate value error has been detected and processing is aborted.
      3. Otherwise, previous context was determined before, and no further processing is necessary.
    11. Create a map defined to use to keep track of whether or not a term has already been defined or currently being defined during recursion.
    12. For each key-value pair in context where key is not @base, @import, @language, @propagate, @protected, @version, or @vocab, invoke the Create Term Definition algorithm, passing result for active context, context for local context, key, defined, the value of the @protected entry from context, if any, for protected, and propagate .
  6. Return result.

4.2 Create Term Definition

This algorithm is called from the Context Processing algorithm to create a term definition in the active context for a term being processed in a local context.

4.2.1 Overview

This section is non-normative.

Term definitions are created by parsing the information in the given local context for the given term. If the given term is a compact IRI, it may omit an IRI mapping by depending on its prefix having its own term definition. If the prefix is an entry in the local context, then its term definition must first be created, through recursion, before continuing. Because a term definition can depend on other term definitions, a mechanism must be used to detect cyclical dependencies. The solution employed here uses a map, defined, that keeps track of whether or not a term has been defined or is currently in the process of being defined. This map is checked before any recursion is attempted.

After all dependencies for a term have been defined, the rest of the information in the local context for the given term is taken into account, creating the appropriate IRI mapping, container mapping, and type mapping or language mapping for the term.

4.2.2 Algorithm

The algorithm has four required and three optional inputs. The required inputs are an active context, a local context, a term, and a map defined. The optional inputs are protected which defaults to false, override protected, defaulting to false, which is used to allow changes to protected terms, and propagate, defaulting to true..

  1. If defined contains the entry term and the associated value is true (indicating that the term definition has already been created), return. Otherwise, if the value is false, a cyclic IRI mapping error has been detected and processing is aborted.
  2. Set the value associated with defined's term entry to false. This indicates that the term definition is now being created but is not yet complete.
  3. Initialize value to a copy of the value associated with the entry term in local context.
  4. If processing mode is json-ld-1.1 and term is @type, value MUST be a map with the entry @container and value @set. Any other value means that a keyword redefinition error has been detected and processing is aborted.
  5. Otherwise, since keywords cannot be overridden, term MUST NOT be a keyword and a keyword redefinition error has been detected and processing is aborted.
  6. Set previous definition to any existing term definition for term in active context.
  7. Otherwise, remove any previous definition from active context.
  8. If value is null, convert it to a map consisting of a single entry whose key is @id and whose value is null.
  9. Otherwise, if value is a string, convert it to a map consisting of a single entry whose key is @id and whose value is value. Set simple term to true.
  10. Otherwise, value MUST be a map, if not, an invalid term definition error has been detected and processing is aborted. Set simple term to false.
  11. Create a new term definition, definition.
  12. If the @protected entry in value is true, or there is no @protected entry in value and the protected parameter is true, set the protected in definition to true.
  13. If value contains the entry @type:
    1. Initialize type to the value associated with the @type entry, which MUST be a string. Otherwise, an invalid type mapping error has been detected and processing is aborted.
    2. Set type to the result of using the IRI Expansion algorithm, passing active context, type for value, true for vocab, local context, and defined. If the expanded type is neither @id, nor @vocab, nor, if processing mode is json-ld-1.1, @json nor @none, nor an absolute IRI, an invalid type mapping error has been detected and processing is aborted.
    3. Set the type mapping for definition to type.
  14. If value contains the entry @reverse:
    1. If value contains @id or @nest, entries, an invalid reverse property error has been detected and processing is aborted.
    2. If the value associated with the @reverse entry is not a string, an invalid IRI mapping error has been detected and processing is aborted.
    3. Otherwise, set the IRI mapping of definition to the result of using the IRI Expansion algorithm, passing active context, the value associated with the @reverse entry for value, true for vocab, local context, and defined. If the result is neither an absolute IRI nor a blank node identifier, i.e., it contains no colon (:), an invalid IRI mapping error has been detected and processing is aborted.
    4. If value contains an @container entry, set the container mapping of definition to its value; if its value is neither @set, nor @index, nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
    5. Set the reverse property flag of definition to true.
    6. Set the term definition of term in active context to definition and the value associated with defined's entry term to true and return.
  15. Set the reverse property flag of definition to false.
  16. If value contains the entry @id and its value does not equal term:
    1. If value contains the @id entry is null, the term is not used for IRI expansion, but is retained to be able to detect future redefinitions of this term.
    2. Otherwise, if the value associated with the @id entry is not a string, an invalid IRI mapping error has been detected and processing is aborted.
    3. Otherwise, set the IRI mapping of definition to the result of using the IRI Expansion algorithm, passing active context, the value associated with the @id entry for value, true for vocab, local context, and defined. If the resulting IRI mapping is neither a keyword, nor an absolute IRI, nor a blank node identifier, an invalid IRI mapping error has been detected and processing is aborted; if it equals @context, an invalid keyword alias error has been detected and processing is aborted.
    4. If the term contains a colon (:) anywhere but as the last character of term, and the result of expanding term using the IRI Expansion algorithm is not the same as the IRI mapping of definition, an invalid IRI mapping error has been detected and processing is aborted.
    5. If term does not contain a colon (:), simple term is true, and the, IRI mapping of definition ends with a URI gen-delim character, set the prefix flag in definition to true.
  17. Otherwise if the term contains a colon (:):
    1. If term is a compact IRI with a prefix that is an entry in local context a dependency has been found. Use this algorithm recursively passing active context, local context, the prefix as term, and defined.
    2. If term's prefix has a term definition in active context, set the IRI mapping of definition to the result of concatenating the value associated with the prefix's IRI mapping and the term's suffix.
    3. Otherwise, term is an absolute IRI or blank node identifier. Set the IRI mapping of definition to term.
  18. Otherwise, if term is @type, set the IRI mapping of definition to @type.
  19. Otherwise, if active context has a vocabulary mapping, the IRI mapping of definition is set to the result of concatenating the value associated with the vocabulary mapping and term. If it does not have a vocabulary mapping, an invalid IRI mapping error been detected and processing is aborted.
  20. If value contains the entry @container:
    1. Initialize container to the value associated with the @container entry, which MUST be either @graph, @id, @index, @language, @list, @set, or @type. or an array containing exactly any one of those keywords, an array containing @graph and either @id or @index optionally including @set, or an array containing a combination of @set and any of @index, @id, @type, @language in any order . Otherwise, an invalid container mapping has been detected and processing is aborted.
    2. If processing mode is json-ld-1.0 and the container value is @graph, @id, or @type, or is otherwise not a string, an invalid container mapping has been detected and processing is aborted.
    3. Set the container mapping of definition to container.
    4. If container mapping is @type:
      1. If type mapping in definition is undefined, set it to @id.
      2. If type mapping in definition is neither @id nor @vocab, an invalid type mapping error has been detected and processing is aborted.
  21. If value contains the entry @index:
    1. If processing mode is json-ld-1.0 or container mapping does not include @index, an invalid term definition has been detected and processing is aborted.
    2. Initialize index to the value associated with the @index entry, which MUST a string expanding to an absolute IRI. Otherwise, an invalid term definition has been detected and processing is aborted.
    3. Set the index mapping of definition to index
  22. If value contains the entry @context:
    1. If processing mode is json-ld-1.0, an invalid term definition has been detected and processing is aborted.
    2. Initialize context to the value associated with the @context entry, which is treated as a local context.
    3. Invoke the Context Processing algorithm using the active context, context as local context, and true for override protected. If any error is detected, an invalid scoped context error has been detected and processing is aborted.
      Note

      The result of the Context Processing algorithm is discarded; it is called to detect errors at definition time. If used, the context will be re-processed and applied to the active context as part of expansion or compaction.

    4. Set the local context of definition to context.
  23. If value contains the entry @language and does not contain the entry @type:
    1. Initialize language to the value associated with the @language entry, which MUST be either null or a string. Otherwise, an invalid language mapping error has been detected and processing is aborted.
    2. If language is a string set it to lowercased language. Set the language mapping of definition to language.
  24. If value contains the entry @nest:
    1. If processing mode is json-ld-1.0, an invalid term definition has been detected and processing is aborted.
    2. Initialize nest value in definition to the value associated with the @nest entry, which MUST be a string and MUST NOT be a keyword other than @nest. Otherwise, an invalid @nest value error has been detected and processing is aborted.
  25. If value contains the entry @prefix:
    1. If processing mode is json-ld-1.0, or if term contains a colon (:), an invalid term definition has been detected and processing is aborted.
    2. Initialize the prefix flag to the value associated with the @prefix entry, which MUST be a boolean. Otherwise, an invalid @prefix value error has been detected and processing is aborted.
  26. If the value contains any entry other than @id, @reverse, @container, @context, @language, @nest, @prefix, or @type, an invalid term definition error has been detected and processing is aborted.
  27. If override protected is false and previous definition exists and is protected;
    1. If definition is not the same as previous definition (other than the value of protected), a protected term redefinition error has been detected, and processing is aborted.
    2. Set definition to previous definition to retain the value of protected.
  28. Set the term definition of term in active context to definition and set the value associated with defined's entry term to true.

4.3 IRI Expansion

In JSON-LD documents, some keys and values may represent IRIs. This section defines an algorithm for transforming a string that represents an IRI into an absolute IRI or blank node identifier. It also covers transforming keyword aliases into keywords.

IRI expansion may occur during context processing or during any of the other JSON-LD algorithms. If IRI expansion occurs during context processing, then the local context and its related defined map from the Context Processing algorithm are passed to this algorithm. This allows for term definition dependencies to be processed via the Create Term Definition algorithm.

4.3.1 Overview

This section is non-normative.

In order to expand value to an absolute IRI, we must first determine if it is null, a term, a keyword alias, or some form of IRI. Based on what we find, we handle the specific kind of expansion; for example, we expand a keyword alias to a keyword and a term to an absolute IRI according to its IRI mapping in the active context. While inspecting value we may also find that we need to create term definition dependencies because we're running this algorithm during context processing. We can tell whether or not we're running during context processing by checking local context against null. We know we need to create a term definition in the active context when value is an entry in the local context and the defined map does not have an entry for value with an associated value of true. The defined map is used during Context Processing to keep track of which terms have already been defined or are in the process of being defined. We create a term definition by using the Create Term Definition algorithm.

4.3.2 Algorithm

The algorithm takes two required and four optional input variables. The required inputs are an active context and a value to be expanded. The optional inputs are two flags, document relative and vocab, that specifying whether value can be interpreted as a relative IRI against the document's base IRI or the active context's vocabulary mapping, respectively, and a local context and a map defined to be used when this algorithm is used during Context Processing. If not passed, the two flags are set to false and local context and defined are initialized to null.

  1. If value is a keyword or null, return value as is.
  2. If local context is not null, it contains an entry with a key that equals value, and the value of the entry for value in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, value as term, and defined. This will ensure that a term definition is created for value in active context during Context Processing.
  3. If active context has a term definition for value, and the associated IRI mapping is a keyword, return that keyword.
  4. If vocab is true and the active context has a term definition for value, return the associated IRI mapping.
  5. If value contains a colon (:), it is either an absolute IRI, a compact IRI, or a blank node identifier:
    1. Split value into a prefix and suffix at the first occurrence of a colon (:).
    2. If prefix is underscore (_) or suffix begins with double-forward-slash (//), return value as it is already an absolute IRI or a blank node identifier.
    3. If local context is not null, it contains a prefix entry, and the value of the prefix entry in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, prefix as term, and defined. This will ensure that a term definition is created for prefix in active context during Context Processing.
    4. If active context contains a term definition for prefix having a non-null IRI mapping and the prefix flag of the term definition is true, return the result of concatenating the IRI mapping associated with prefix and suffix.
      Editor's note

      A more conservative change, although more involved, would to restrict looking at the prefix flag unless the processing mode is json-ld-1.1.

    5. If value has the form of an absolute IRI, return value.
  6. If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
  7. Otherwise, if document relative is true set value to the result of resolving value against the base IRI. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization 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].
  8. Return value as is.

5. Expansion Algorithms

5.1 Expansion Algorithm

This algorithm expands a JSON-LD document, such that all context definitions are removed, all terms and compact IRIs are expanded to absolute IRIs, blank node identifiers, or keywords and all JSON-LD values are expressed in arrays in expanded form.

5.1.1 Overview

This section is non-normative.

Starting with its root element, we can process the JSON-LD document recursively, until we have a fully expanded result. When expanding an element, we can treat each one differently according to its type, in order to break down the problem:

  1. If the element is null, there is nothing to expand.
  2. Otherwise, if element is a scalar, we expand it according to the Value Expansion algorithm.
  3. Otherwise, if the element is an array, then we expand each of its items recursively and return them in a new array.
  4. Otherwise, element is a map. We expand each of its entries, adding them to our result, and then we expand each value for each entry recursively. Some of the entry keys will be terms or compact IRIs and others will be keywords or simply ignored because they do not have definitions in the context. Any IRIs will be expanded using the IRI Expansion algorithm.

Finally, after ensuring result is in an array, we return result.

5.1.2 Algorithm

The algorithm takes three required and three optional input variables. The required inputs are an active context, an active property, and an element to be expanded. The optional inputs are the frameExpansion flag allowing special forms of input used for frame expansion, the ordered flag, used to order map entry keys lexicographically, where noted, and the from map flag, used to control reverting previous term definitions in the active context associated with non-propagated contexts. To begin, the active property is set to null, and element is set to the JSON-LD input. If not passed, the both flags are set to false.

The algorithm also performs processing steps specific to expanding a JSON-LD Frame. For a frame, the @id and @type entries can accept an array of IRIs or an empty map. The entries of a value object can also accept an array of strings, or an empty map. Framing also uses additional keyword entries: (@explicit, @default, @embed, @explicit, @omitDefault, or @requireAll) which are preserved through expansion. Special processing for a JSON-LD Frame is invoked when the frameExpansion flag is set to true.

Note

As mentioned in Terms [JSON-LD11], to avoid forward-compatibility issues, terms should not start with an @ character as future versions of JSON-LD may introduce additional keywords. This step will treat such terms like any other term, i.e., they are ignored unless mapped to an IRI. Furthermore, the use of empty terms ("") is not allowed as not all programming languages are able to handle empty JSON keys. Implementations of this algorithm may consider providing a runtime flag to show a warning if such terms are encountered.

  1. If element is null, return null.
  2. If active property is @default, set the frameExpansion flag to false.
  3. If active property has a term definition in active context with a local context, set property scoped context to that local context.
  4. If element is a scalar,
    1. If active property is null or @graph, drop the free-floating scalar by returning null.
    2. If property-scoped context is defined, set active context to the result of the Context Processing algorithm, passing active context and property-scoped context as local context.
    3. Return the result of the Value Expansion algorithm, passing the active context, active property, and element as value.
  5. If element is an array,
    1. Initialize an empty array, result.
    2. For each item in element:
      1. Initialize expanded item to the result of using this algorithm recursively, passing active context, active property, item as element, the frameExpansion ordered, and from map flags.
      2. If the container mapping of active property includes @list, and expanded item is an array, set expanded item to a new map containing the entry @list where the value is the original expanded item.
      3. If expanded item is an array, append each of its items to result. Otherwise, if expanded item is not null, append it to result.
    3. Return result.
  6. Otherwise element is a map.
  7. If active context has a previous context, the active context is not propagated. If from map is undefined or false, and element does not contain a entry expanding to @value, and element does not consist of a single entry expanding to @id, set active context to previous context from active context, as the scope of a term-scoped context does not apply when processing new node objects.
  8. If property-scoped context is defined, set active context to the result of the Context Processing algorithm, passing active context and property-scoped context as local context.
  9. If element contains the entry @context, set active context to the result of the Context Processing algorithm, passing active context and the value of the @context entry as local context.
  10. Set type-scoped context to active context. This is used for expanding values that may be relevant to any previous type-scoped context.
  11. For each key and value in element ordered lexicographically by key where key expands to @type using the IRI Expansion algorithm, passing active context, key for value, and true for vocab:
    1. Convert value into an array, if necessary.
    2. For each term which is a value of value ordered lexicographically, if term is a string, and term's term definition in active context has a local context, set active context to the result to the result of the Context Processing algorithm, passing active context, the value of the term's local context as local context, and true for propagate.
  12. Initialize two empty maps, result and nests. Set input type to the last value of the first entry in element expanding to @type, ordering entries lexicographically by key.
  13. For each key and value in element, ordered lexicographically by key if ordered is true:
    1. If key is @context, continue to the next key.
    2. Set expanded property to the result of using the IRI Expansion algorithm, passing active context, key for value, and true for vocab.
    3. If expanded property is null or it neither contains a colon (:) nor it is a keyword, drop key by continuing to the next key.
    4. If expanded property is a keyword:
      1. If active property equals @reverse, an invalid reverse property map error has been detected and processing is aborted.
      2. If result has already an expanded property entry, other than @included or @type, a colliding keywords error has been detected and processing is aborted.
      3. If expanded property is @id and value is not a string, an invalid @id value error has been detected and processing is aborted. Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing active context, value, and true for document relative. When the frameExpansion flag is set, value may be an empty map, or an array of one or more strings. expanded value will be an array of one or more of these, with string values expanded using the IRI Expansion Algorithm.
      4. If expanded property is @type and value is neither a string nor an array of strings, an invalid type value error has been detected and processing is aborted. Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing type-scoped context for active context, true for vocab, and true for document relative to expand the value or each of its items. If result already has an entry for @type, prepend the value of @type in result to expanded value, transforming it into an array, if necessary. When the frameExpansion flag is set, value may also be an empty map.
        Note
        No transformation from a string value to an array expanded value is implied, and the form or value should be preserved in expanded value.
      5. If expanded property is @graph, set expanded value to the result of using this algorithm recursively passing active context, @graph for active property, value for element, and the frameExpansion and ordered flags, ensuring that expanded value is an array of one or more maps.
      6. If expanded property is @included and processing mode is json-ld-1.1, set expanded value to the result of using this algorithm recursively passing active context, active property, value for element, and the frameExpansion and ordered flags, ensuring that the result is an array. If any element of included result is not a node object, an invalid @included value error has been detected and processing is aborted. If result already has an entry for @include, prepend the value of @include in result to expanded value.
      7. Otherwise, if expanded property is @value, processing mode is json-ld-1.1, and input type is @json, set expanded value to value. Otherwise, if value is not a scalar or null, an invalid value object value error has been detected and processing is aborted. Otherwise, set expanded value to value. If expanded value is null, set the @value entry of result to null and continue with the next key from element. Null values need to be preserved in this case as the meaning of an @type entry depends on the existence of an @value entry. When the frameExpansion flag is set, value may also be an empty map or an array of scalar values. expanded value will be null, or an array of one or more scalar values.
      8. If expanded property is @language and value is not a string, an invalid language-tagged string error has been detected and processing is aborted. Otherwise, set expanded value to lowercased value. When the frameExpansion flag is set, value may also be an empty map or an array of zero or strings. expanded value will be an array of one or more string values converted to lower case.
      9. If expanded property is @index and value is not a string, an invalid @index value error has been detected and processing is aborted. Otherwise, set expanded value to value.
      10. If expanded property is @list:
        1. If active property is null or @graph, continue with the next key from element to remove the free-floating list.
        2. Otherwise, initialize expanded value to the result of using this algorithm recursively passing active context, active property, value for element, and the frameExpansion and ordered flags.
      11. If expanded property is @set, set expanded value to the result of using this algorithm recursively, passing active context, active property, value for element, and the frameExpansion and ordered flags.
      12. If expanded property is @reverse and value is not a map, an invalid @reverse value error has been detected and processing is aborted. Otherwise
        1. Initialize expanded value to the result of using this algorithm recursively, passing active context, @reverse as active property, value as element, and the frameExpansion and ordered flags.
        2. If expanded value contains an @reverse entry, i.e., properties that are reversed twice, execute for each of its property and item the following steps:
          1. If result does not have a property entry, create one and set its value to an empty array.
          2. Append item to the value of the property entry of result.
        3. If expanded value contains an entry other than @reverse:
          1. If result does not have an @reverse entry, create one and set its value to an empty map.
          2. Reference the value of the @reverse entry in result using the variable reverse map.
          3. For each property and items in expanded value other than @reverse:
            1. For each item in items:
              1. If item is a value object or list object, an invalid reverse property value has been detected and processing is aborted.
              2. If reverse map has no property entry, create one and initialize its value to an empty array.
              3. Append item to the value of the property entry in reverse map.
        4. Continue with the next key from element.
      13. If expanded property is @nest, add key to nests, initializing it to an empty array, if necessary. Continue with the next key from element.
      14. When the frameExpansion flag is set, if expanded property is any other framing keyword (@explicit, @default, @embed, @explicit, @omitDefault, or @requireAll), set expanded value to the result of performing the Expansion Algorithm recursively, passing active context, active property, value for element, and the frameExpansion and ordered flags.
      15. Unless expanded value is null, set the expanded property entry of result to expanded value.
      16. Continue with the next key from element.
    5. Set container mapping to key's container mapping in active context.
    6. If key's term definition in active context has a type mapping of @json, set expanded value to a new map, set the entry @value to value, and set the entry @type to @json.
    7. Otherwise, if container mapping includes @language and value is a map then value is expanded from a language map as follows:
      1. Initialize expanded value to an empty array.
      2. For each key-value pair language-language value in value, ordered lexicographically by language if ordered is true:
        1. If language value is not an array set it to an array containing only language value.
        2. For each item in language value:
          1. item must be a string or null, otherwise an invalid language map value error has been detected and processing is aborted.
          2. Append a map to expanded value that consists of two key-value pairs: (@value-item) and (@language-lowercased language), unless item is null. If language is @none, or expands to @none, do not set the @language entry.
    8. Otherwise, if container mapping includes @index, @type, or @id and value is a map then value is expanded from an map as follows:
      1. Initialize expanded value to an empty array.
      2. Initialize index key to the key's index mapping in active context, or @index, if it does not exist.
      3. For each key-value pair index-index value in value, ordered lexicographically by index if ordered is true:
        1. If container mapping includes @type:
          1. Set map context to the previous context from active context if it exists, or active context otherwise.
          2. If index's term definition in map context has a local context, update map context to the result of the Context Processing algorithm, passing map context as active context and the value of the index's local context as local context.
        2. Otherwise, set map context to active context.
        3. Set expanded index to the result of using the IRI Expansion algorithm, passing active context, index, and true for vocab.
        4. If index value is not an array set it to an array containing only index value.
        5. Initialize index value to the result of using this algorithm recursively, passing map context as active context, key as active property, index value as element, and the frameExpansion and ordered flags.
        6. For each item in index value:
          1. If container mapping includes @graph and if item is not a graph object, set item to a new map containing the key-value pair @graph-item, ensuring that the value is represented using an array.
          2. If container mapping includes @index, index key is not @index, item does not have an entry @index and expanded index is not @none, set index property values to the concatenation of expanded index with any existing values of index key in item. Add the key-value pair (expanded index-index property values) to item. If item is a value object, it MUST NOT contain any extra properties; an invalid value object error has been detected and processing is aborted.
          3. Otherwise, if container mapping includes @index, item does not have an entry @index, and expanded index is not @none, add the key-value pair (@index-index) to item.
          4. Otherwise, if container mapping includes @id and item does not have the entry @id, add the key-value pair (@id-expanded index) to item, where expanded index is set to the result of using the IRI Expansion algorithm, passing active context, index, and true for document relative, unless expanded index is already set to @none.
          5. Otherwise, if container mapping includes @type set types to the concatenation of expanded index with any existing values of @type in item. If expanded index is @none, do not concatenate expanded index to types. Add the key-value pair (@type-types) to item.
          6. Append item to expanded value.
    9. Otherwise, initialize expanded value to the result of using this algorithm recursively, passing active context, key for active property, value for element, and the frameExpansion and ordered flags.
    10. If expanded value is null, ignore key by continuing to the next key from element.
    11. If container mapping includes @list and expanded value is not already a list object, convert expanded value to a list object by first setting it to an array containing only expanded value if it is not already an array, and then by setting it to a map containing the key-value pair @list-expanded value.
    12. If container mapping includes @graph, convert expanded value into an array, if necessary, then convert each value ev in expanded value into a graph object:
      1. If ev is not a graph object, convert it into one by creating a map containing the key-value pair @graph-ev where ev is represented as an array.
    13. If the term definition associated to key indicates that it is a reverse property
      1. If result has no @reverse entry, create one and initialize its value to an empty map.
      2. Reference the value of the @reverse entry in result using the variable reverse map.
      3. If expanded value is not an array, set it to an array containing expanded value.
      4. For each item in expanded value
        1. If item is a value object or list object, an invalid reverse property value has been detected and processing is aborted.
        2. If reverse map has no expanded property entry, create one and initialize its value to an empty array.
        3. Append item to the value of the expanded property entry of reverse map.
    14. Otherwise, key is not a reverse property:
      1. If result does not have an expanded property entry, create one and initialize its value to an empty array.
      2. Append expanded value to value of the expanded property entry of result.
    15. For each key nesting-key in nests
      1. Set nested values to the value of nesting-key in element, ensuring that it is an array.
      2. For each nested value in nested values:
        1. If nested value is not a map, or any key within nested value expands to @value, an invalid @nest value error has been detected and processing is aborted.
        2. Recursively repeat step 9 using nested value for element.
  14. If result contains the entry @value:
    1. The result must not contain any entries other than @value, @language, @type, and @index. It must not contain both a @language entry and an @type entry. Otherwise, an invalid value object error has been detected and processing is aborted.
    2. If the value of result's @value entry is null, then set result to null.
    3. Otherwise, if the result's @type entry is @json, then the @value entry may contain any value, and is treated as a JSON literal.
    4. Otherwise, if the value of result's @value entry is not a string and result contains the entry @language, an invalid language-tagged value error has been detected (only strings can be language-tagged) and processing is aborted.
    5. Otherwise, if the result has an @type entry and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
  15. Otherwise, if result contains the entry @type and its associated value is not an array, set it to an array containing only the associated value.
  16. Otherwise, if result contains the entry @set or @list:
    1. The result must contain at most one other entry which must be @index. Otherwise, an invalid set or list object error has been detected and processing is aborted.
    2. If result contains the entry @set, then set result to the entry's associated value.
  17. If result contains only the entry @language, set result to null.
  18. If active property is null or @graph, drop free-floating values as follows:
    1. If result is an empty map or contains the entries @value or @list, set result to null.
    2. Otherwise, if result is a map whose only entry is @id, set result to null. When the frameExpansion flag is set, a map containing only the @id entry is retained.
  19. Return result.

If, after the above algorithm is run, the result is a map that contains only an @graph entry, set the result to the value of @graph's value. Otherwise, if the result is null, set it to an empty array. Finally, if the result is not an array, then set the result to an array containing only the result.

5.2 Value Expansion

Some values in JSON-LD can be expressed in a compact 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.

5.2.1 Overview

This section is non-normative.

If active property has a type mapping in the active context set to @id or @vocab, and the value is a string, a map with a single entry @id whose value is the result of using the IRI Expansion algorithm on value is returned.

Otherwise, the result will be a map containing an @value entry whose value is the passed value. Additionally, an @type entry will be included if there is a type mapping associated with the active property or an @language entry if value is a string and there is language mapping associated with the active property.

Note that values interpreted as IRIs fall into two categories: those that are document relative, and those that are vocabulary relative. Properties and values of @type, along with terms marked as "@type": "@vocab" are vocabulary relative, meaning that they need to be either a defined term, a compact IRI where the prefix is a term, or a string which is turned into an absolute IRI using the vocabulary mapping.

5.2.2 Algorithm

The algorithm takes three required inputs: an active context, an active property, and a value to expand.

  1. If the active property has a type mapping in active context that is @id, and the value is a string, return a new map containing a single entry where the key is @id and the value is the result of using the IRI Expansion algorithm, passing active context, value, and true for document relative.
  2. If active property has a type mapping in active context that is @vocab, and the value is a string, return a new map containing a single entry where the key is @id and the value is the result of using the IRI Expansion algorithm, passing active context, value, true for vocab, and true for document relative.
  3. Otherwise, initialize result to a map with an @value entry whose value is set to value.
  4. If active property has a type mapping in active context, other than @id, @vocab, or @none, add an @type entry to result and set its value to the value associated with the type mapping.
  5. Otherwise, if value is a string:
    1. If a language mapping is associated with active property in active context, add an @language to result and set its value to the language code associated with the language mapping; unless the language mapping is set to null in which case no such entry is added.
    2. Otherwise, if the active context has a default language, add an @language to result and set its value to the default language.
  6. Return result.

6. Compaction Algorithms

6.1 Compaction Algorithm

This algorithm compacts a JSON-LD document, such that the given context is applied. This must result in shortening any applicable IRIs to terms or compact IRIs, any applicable keywords to keyword aliases, and any applicable JSON-LD values expressed in expanded form to simple values such as strings or numbers.

6.1.1 Overview

This section is non-normative.

Starting with its root element, we can process the JSON-LD document recursively, until we have a fully compacted result. When compacting an element, we can treat each one differently according to its type, in order to break down the problem:

  1. If the element is a scalar, it is already in compacted form, so we simply return it.
  2. If the element is an array, we compact each of its items recursively and return them in a new array.
  3. Otherwise element is a map. The value of each entry in element is compacted recursively. Some of the entry keys will be compacted, using the IRI Compaction algorithm, to terms or compact IRIs and others will be compacted from keywords to keyword aliases or simply left unchanged because they do not have definitions in the context. Values will be converted to compacted form via the Value Compaction algorithm. Some data will be reshaped based on container mapping specified in the context such as @index or @language maps.

The final output is a map with an @context entry, if a non-empty context was given, where the map is either result or a wrapper for it where result appears as the value of an (aliased) @graph entry because result contained two or more items in an array.

6.1.2 Algorithm

The algorithm takes four required and two optional input variables. The required inputs are an active context, an inverse context, an active property, and an element to be compacted. The optional inputs are the compactArrays flag and the ordered flag, used to order map entry keys lexicographically, where noted. To begin, the active context is set to the result of performing Context Processing on the passed context, the inverse context is set to the result of performing the Inverse Context Creation algorithm on active context, the active property is set to null, element is set to the result of performing the Expansion algorithm on the JSON-LD input. If not passed, the both flags are set to false.

  1. Set type-scoped context to active context. This is used for compacting values that may be relevant to any previous type-scoped context.
  2. If element is a scalar, it is already in its most compact form, so simply return element.
  3. If element is an array:
    1. Initialize result to an empty array.
    2. For each item in element:
      1. Initialize compacted item to the result of using this algorithm recursively, passing active context, inverse context, active property, item for element, and the compactArrays and ordered flags.
      2. If compacted item is not null, then append it to result.
    3. If result contains only one item (it has a length of 1), active property is not @graph or @set, or the container mapping for active property in active context does not include @list or @set, and compactArrays is true, set result to its only item.
    4. Return result.
  4. Otherwise element is a map.
  5. If active context has a previous context, the active context is not propagated. If element does not contain an @value entry, and element does not consist of a single @id entry, set active context to previous context from active context, as the scope of a term-scoped context does not apply when processing new node objects.
  6. If the term definition for active property has a local context:
    1. Set active context to the result of the Context Processing algorithm, passing active context, the value of the active property's local context as local context, and true for override protected.
    2. Set inverse context using the Inverse Context Creation algorithm using active context.
  7. If element has an @value or @id entry and the result of using the Value Compaction algorithm, passing active context, inverse context, active property,and element as value is a scalar, or the term definition for active property has a type mapping of @json, return that result.
  8. If element is a list object, and the container mapping for active property in active context is @list, return the result of using this algorithm recursively, passing active context, inverse context, active property, value of @list in element for element, and the compactArrays and ordered flags.
  9. Initialize inside reverse to true if active property equals @reverse, otherwise to false.
  10. Initialize result to an empty map.
  11. If element has an @type entry, create a new array compacted types initialized by transforming each expanded type of that entry into it's compacted form using the IRI Compaction algorithm, passing active context, inverse context, expanded type for var, true for vocab, and false for propagate. Then, for each term in compacted types ordered lexicographically:
    1. If the term definition for term in type-scoped context has a local context:
      1. Set active context to the result of the Context Processing algorithm, passing active context and the value of term's local context in type-scoped context as local context.
      2. Set inverse context using the Inverse Context Creation algorithm using active context.
  12. For each key expanded property and value expanded value in element, ordered lexicographically by expanded property if ordered is true:
    1. If expanded property is @id:
      1. If expanded value is a string, then initialize compacted value to the result of using the IRI Compaction algorithm, passing active context, inverse context, and expanded value for var.
      2. Initialize alias to the result of using the IRI Compaction algorithm, passing active context, inverse context, expanded property for var, and true for vocab.
      3. Add an entry alias to result whose value is set to compacted value and continue to the next expanded property.
    2. If expanded property is @type:
      1. If expanded value is a string, then initialize compacted value to the result of using the IRI Compaction algorithm, passing type-scoped context for active context, inverse context, expanded value for var, and true for vocab.
      2. Otherwise, expanded value must be a @type array:
        1. Initialize compacted value to an empty array.
        2. For each item expanded type in expanded value:
          1. Set term to the result of of using the IRI Compaction algorithm, passing type-scoped context for active context, inverse context, expanded type for var, and true for vocab.
          2. Append term, to compacted value.
        3. If compacted value contains only one item (it has a length of 1), then set compacted value to its only item.
      3. Initialize alias to the result of using the IRI Compaction algorithm, passing active context, inverse context, expanded property for var, and true for vocab.
      4. If processing mode is json-ld-1.1, and the term definition for alias in the active context has a container mapping including @set, ensure that compacted value is an array.
      5. Add an entry alias to result whose value is set to compacted value and continue to the next expanded property.
    3. If expanded property is @reverse:
      1. Initialize compacted value to the result of using this algorithm recursively, passing active context, inverse context, @reverse for active property, expanded value for element, and the compactArrays and ordered flags.
      2. For each property and value in compacted value:
        1. If the term definition for property in the active context indicates that property is a reverse property
          1. If the term definition for property in the active context has a container mapping including @set or compactArrays is false, and value is not an array, set value to a new array containing only value.
          2. If property is not an entry of result, add one and set its value to value.
          3. Otherwise, if the value of the property entry of result is not an array, set it to a new array containing only the value. Then append value to its value if value is not an array, otherwise append each of its items.
          4. Remove the property entry from compacted value.
      3. If compacted value has some remaining map entries, i.e., it is not an empty map:
        1. Initialize alias to the result of using the IRI Compaction algorithm, passing active context, inverse context, @reverse for var, and true for vocab.
        2. Set the value of the alias entry of result to compacted value.
      4. Continue with the next expanded property from element.
    4. If expanded property is @preserve then:
      1. Initialize compacted value to the result of using this algorithm recursively, passing active context, inverse context, property for active property, expanded value for element, and the compactArrays and ordered flags.
      2. Add compacted value as the value of @preserve in result unless expanded value is an empty array.
    5. If expanded property is @index and active property has a container mapping in active context that includes @index, then the compacted result will be inside of an @index container, drop the @index entry by continuing to the next expanded property.
    6. Otherwise, if expanded property is @index, @value, or @language:
      1. Initialize alias to the result of using the IRI Compaction algorithm, passing active context, inverse context, expanded property for var, and true for vocab.
      2. Add an entry alias to result whose value is set to expanded value and continue with the next expanded property.
    7. If expanded value is an empty array:
      1. Initialize item active property to the result of using the IRI Compaction algorithm, passing active context, inverse context, expanded property for var, expanded value for value, true for vocab, and inside reverse.
      2. If the term definition for item active property in the active context has a nest value, that value (nest term) must be @nest, or a term in the active context that expands to @nest, otherwise an invalid @nest value error has been detected, and processing is aborted. If result does not have a nest term entry, initialize it to an empty map (nest object). If nest object does not have an item active property entry, set this entry's value in nest object to an empty array.Otherwise, if the entry's value is not an array, then set it to one containing only the value.
      3. Otherwise, if result does not have an item active property entry, set this entry's value in result to an empty array. Otherwise, if the entry's value is not an array, then set it to one containing only the value.
    8. At this point, expanded value must be an array due to the Expansion algorithm. For each item expanded item in expanded value:
      1. Initialize item active property to the result of using the IRI Compaction algorithm, passing active context, inverse context, expanded property for var, expanded item for value, true for vocab, and inside reverse.
      2. If the term definition for item active property in the active context has a nest value entry, that value (nest term) must be @nest, or a term in the active context that expands to @nest, otherwise an invalid @nest value error has been detected, and processing is aborted. Set nest result to the value of nest term in result, initializing it to a new map, if necessary; otherwise set nest result to result.
      3. Initialize container to null. If there is a container mapping for item active property in active context, set container to the first such value other than @set.
      4. Initialize as array to true or false depending on if the container mapping for item active property in active context includes @set or if item active property is @graph or @list.
      5. Initialize compacted item to the result of using this algorithm recursively, passing active context, inverse context, item active property for active property, expanded item for element if it does not contain the entry @list and is not a graph object containing @list, otherwise pass the value of the entry for element. Along with the compactArrays and ordered flags
      6. If expanded item is a list object:
        1. If compacted item is not an array, then set it to an array containing only compacted item.
        2. If container is not @list:
          1. Convert compacted item to a list object by setting it to a map containing an entry where the key is the result of the IRI Compaction algorithm, passing active context, inverse context, @list for var, and compacted item for value and the value is the original compacted item.
          2. If expanded item contains the entry @index, then add an entry to compacted item where the key is the result of the IRI Compaction algorithm, passing active context, inverse context, @index as var, and the value associated with the @index entry in expanded item as value.
        3. Otherwise, append compacted item to the value associated with the item active property entry in nest result, initializing it to a new empty array, if necessary.
      7. If expanded item is a graph object:
        1. If container includes @graph and @id:
          1. Initialize map object to the value of item active property in nest result.
          2. Initialize map key to the result of calling the IRI Compaction algorithm passing active context and the value of @id in expanded item or @none if no such value exists as var, with vocab set to true if there is no @id entry in expanded item.
          3. If compacted item is not an array and as array is true, set compacted item to an array containing that value.
          4. If map key is not an entry in map object, then set this entry's value in map object to compacted item. Otherwise, if the value is not an array, then set it to one containing only the value and then append compacted item to it.
        2. Otherwise, if container includes @graph and @index and expanded item is a simple graph object:
          1. Initialize map object to the value of item active property in nest result.
          2. Initialize map key the value of @index in expanded item or @none, if no such value exists.
          3. If compacted item is not an array and as array is true, set compacted item to an array containing that value.
          4. If map key is not an entry in map object, then set this entry's value in map object to compacted item. Otherwise, if the value is not an array, then set it to one containing only the value and then append compacted item to it.
        3. Otherwise, if container includes @graph and expanded item is a simple graph object the value cannot be represented as a map object. If compacted item is not an array and as array is true, set compacted item to an array containing that value. If the value of an item active property entry in nest result is not an array, set it to a new array containing only the value. Then append compacted item to the value if compacted item is not an array, otherwise, concatenate it.
        4. Otherwise, container does not include @graph or otherwise does not match one of the previous cases, redo compacted item.
          1. Set compacted item to a new map containing the key resulting from calling the IRI Compaction algorithm passing active context, @graph as var, and true for vocab using the original compacted item as a value.
          2. If expanded item contains an @id entry, add the key resulting from calling the IRI Compaction algorithm passing active context, @id as var, and true for vocab using the value resulting from calling the IRI Compaction algorithm passing active context, the value of @id in expanded item as var.
          3. If expanded item contains an @index entry, add the key resulting from calling the IRI Compaction algorithm passing active context, @index as var, and true for vocab using the value of @index in expanded item.
          4. If as array is true, set compacted item to an array containing that value.
          5. Then append compacted item to the value if compacted item is not an array, otherwise, concatenate it.
      8. Otherwise, if container includes @language, @index, @id, or @type and container does not include @graph:
        1. If item active property is not an entry in nest result, initialize it to an empty map. Initialize map object to the value of item active property in nest result.
        2. Set container key to the result of calling the IRI Compaction algorithm passing active context, either @language, @index, @id, or @type based on the contents of container, as var, and true for vocab.
        3. Set index key to the value of index mapping in the term definition associated with item active property in active context, or @index, if no such value exists.
        4. If container includes @language and expanded item contains a @value entry, then set compacted item to the value associated with its @value entry. Set map key to the value of @language in expanded item, if any.
        5. Otherwise, if container includes @index and index key is @index, set map key to the value of @index in expanded item, if any, and remove container key from compacted item.
        6. Otherwise, if container includes @index and index key is not @index, Set map key to the first value of container key in compacted item, if any. If there are remaining values in compacted item for container key, set the value of container key in compacted item to those remaining values. Otherwise, remove that entry from compacted item.
        7. Otherwise, if container includes @id, set map key to the value of container key in compacted item and remove container key from compacted item.
        8. Otherwise, if container is @type:
          1. Set map key to the first value of container key in compacted item, if any.
          2. If there are remaining values in compacted item for container key, set the value of container key in compacted item to those remaining values.
          3. Otherwise, remove that entry from compacted item.
          4. If compacted item contains a single entry with a key expanding to @id, set compacted item to the result of using this algorithm recursively, passing active context, inverse context, item active property for active property, and a map composed of the single entry for @id from expanded item for element.
        9. If compacted item is not an array and as array is true, set compacted item to an array containing that value.
        10. If map key is null, set it to the result of calling the IRI Compaction algorithm passing active context, @none as var, and true for vocab.
        11. If map key is not an entry of map object, then set this entry's value in map object to compacted item. Otherwise, if the value is not an array, then set it to one containing only the value and then append compacted item to it.
      9. Otherwise,
        1. If compactArrays is false, as array is true and compacted item is not an array, set it to a new array containing only compacted item.
        2. If item active property is not an entry in result then add the entry, (item active property-compacted item), to nest result.
        3. Otherwise, if the value associated with the item active property entry in nest result is not an array, set it to a new array containing only the value. Then append compacted item to the value if compacted item is not an array, otherwise, concatenate it.
  13. Return result.

If, after the algorithm outlined above is run, result is an empty array, replace it with a new map. Otherwise, if result is an array, replace it with a new map with a single entry whose key is the result of using the IRI Compaction algorithm, passing active context, inverse context, and @graph as var and whose value is the array result.

Finally, if a non-empty context has been passed, add an @context entry to result and set its value to the passed context.

6.2 Inverse Context Creation

When there is more than one term that could be chosen to compact an IRI, it has to be ensured that the term selection is both deterministic and represents the most context-appropriate choice whilst taking into consideration algorithmic complexity.

In order to make term selections, the concept of an inverse context is introduced. An inverse context is essentially a reverse lookup table that maps container mapping, type mappings, and language mappings to a simple term for a given active context. A inverse context only needs to be generated for an active context if it is being used for compaction.

To make use of an inverse context, a list of preferred container mapping and the type mapping or language mapping are gathered for a particular value associated with an IRI. These parameters are then fed to the Term Selection algorithm, which will find the term that most appropriately matches the value's mappings.

6.2.1 Overview

This section is non-normative.

To create an inverse context for a given active context, each term in the active context is visited, ordered by length, shortest first (ties are broken by choosing the lexicographically least term). For each term, an entry is added to the inverse context for each possible combination of container mapping and type mapping or language mapping that would legally match the term. Illegal matches include differences between a value's type mapping or language mapping and that of the term. If a term has no container mapping, type mapping, or language mapping (or some combination of these), then it will have an entry in the inverse context using the special key @none. This allows the Term Selection algorithm to fall back to choosing more generic terms when a more specifically-matching term is not available for a particular IRI and value combination.

6.2.2 Algorithm

The algorithm takes one required input: the active context that the inverse context is being created for.

  1. Initialize result to an empty map.
  2. Initialize default language to @none. If the active context has a default language, set default language to it.
  3. For each key term and value term definition in the active context, ordered by shortest term first (breaking ties by choosing the lexicographically least term):
    1. If the term definition is null, term cannot be selected during compaction, so continue to the next term.
    2. Initialize container to @none. If the container mapping is not empty, set container to the concatenation of all values of the container mapping in lexicographically order .
    3. Initialize var to the value of the IRI mapping for the term definition.
    4. If var is not an entry of result, add a entry where the key is var and the value is an empty map to result.
    5. Reference the value associated with the var entry in result using the variable container map.
    6. If container map has no container entry, create one and set its value to a new map with three entries. The first entry is @language and its value is a new empty map, the second entry is @type and its value is a new empty map, and the third entry is @any and its value is a new map with the entry @none set to the term being processed.
    7. Reference the value associated with the container entry in container map using the variable type/language map.
    8. If the term definition indicates that the term represents a reverse property:
      1. Reference the value associated with the @type entry in type/language map using the variable type map.
      2. If type map does not have an @reverse entry, create one and set its value to the term being processed.
    9. Otherwise, if term definition has a type mapping which is @none:
      1. Reference the value associated with the @language entry in type/language map using the variable language map.
      2. If language map does not have an @any entry, create one and set its value to the term being processed.
      3. Reference the value associated with the @type entry in type/language map using the variable type map.
      4. If type map does not have an @any entry, create one and set its value to the term being processed.
    10. Otherwise, if term definition has a type mapping:
      1. Reference the value associated with the @type entry in type/language map using the variable type map.
      2. If type map does not have a entry corresponding to the type mapping in term definition, create one and set its value to the term being processed.
    11. Otherwise, if term definition has a language mapping (might be null):
      1. Reference the value associated with the @language entry in type/language map using the variable language map.
      2. If the language mapping equals null, set language to @null; otherwise set it to the language code in language mapping.
      3. If language map does not have a language entry, create one and set its value to the term being processed.
    12. Otherwise:
      1. Reference the value associated with the @language entry in type/language map using the variable language map.
      2. If language map does not have a default language entry, create one and set its value to the term being processed.
      3. If language map does not have an @none entry, create one and set its value to the term being processed.
      4. Reference the value associated with the @type entry in type/language map using the variable type map.
      5. If type map does not have an @none entry, create one and set its value to the term being processed.
  4. Return result.

6.3 IRI Compaction

This algorithm compacts an IRI to a term or compact IRI, or a keyword to a keyword alias. A value that is associated with the IRI may be passed in order to assist in selecting the most context-appropriate term.

6.3.1 Overview

This section is non-normative.

If the passed IRI is null, we simply return null. Otherwise, we first try to find a term that the IRI or keyword can be compacted to if it is relative to active context's vocabulary mapping. In order to select the most appropriate term, we may have to collect information about the passed value. This information includes which container mapping would be preferred for expressing the value, and what its type mapping or language mapping is. For JSON-LD lists, the type mapping or language mapping will be chosen based on the most specific values that work for all items in the list. Once this information is gathered, it is passed to the Term Selection algorithm, which will return the most appropriate term to use.

If no term was found that could be used to compact the IRI, an attempt is made to compact the IRI using the active context's vocabulary mapping, if there is one. If the IRI could not be compacted, an attempt is made to find a compact IRI. A term will be used to create a compact IRI only if the term definition contains the prefix flag with the value true. If there is no appropriate compact IRI, and the compactToRelative option is true, the IRI is transformed to a relative IRI using the document's base IRI. Finally, if the IRI or keyword still could not be compacted, it is returned as is.

In the case were this algorithm would return the input IRI as is, and that IRI can be mistaken for a compact IRI in the active context, this algorithm will raise an error, because it has no way to return an unambiguous representation of the original IRI.

6.3.2 Algorithm

This algorithm takes three required inputs and three optional inputs. The required inputs are an active context, an inverse context, and the var to be compacted. The optional inputs are a value associated with the var, a vocab flag which specifies whether the passed var should be compacted using the active context's vocabulary mapping, and a reverse flag which specifies whether a reverse property is being compacted. If not passed, value is set to null and vocab and reverse are both set to false.

  1. If var is null, return null.
  2. If vocab is true and var is an entry of inverse context:
    1. Initialize default language to active context's default language, if it has one, otherwise to @none.
    2. If value is a map containing the entry @preserve, use the first element from the value of @preserve as value.
    3. Initialize containers to an empty array. This array will be used to keep track of an ordered list of preferred container mapping for a term, based on what is compatible with value.
      Note
      Algorithm steps may append the same value to containers, but the order in which they are added is significant for choosing the most appropriate term.
    4. Initialize type/language to @language, and type/language value to @null. These two variables will keep track of the preferred type mapping or language mapping for a term, based on what is compatible with value.
    5. If value is a map, that contains the an @index entry, and value is not a graph object then append the values @index and @index@set to containers.
    6. If reverse is true, set type/language to @type, type/language value to @reverse, and append @set to containers.
    7. Otherwise, if value is a list object, then set type/language and type/language value to the most specific values that work for all items in the list as follows:
      1. If @index is not an entry in value, then append @list to containers.
      2. Initialize list to the array associated with the @list entry in value.
      3. Initialize common type and common language to null. If list is empty, set common language to default language.
      4. For each item in list:
        1. Initialize item language to @none and item type to @none.
        2. If item contains an @value entry:
          1. If item contains the an @language entry, then set item language to its associated value.
          2. Otherwise, if item contains the a @type entry, set item type to its associated value.
          3. Otherwise, set item language to @null.
        3. Otherwise, set item type to @id.
        4. If common language is null, set it to item language.
        5. Otherwise, if item language does not equal common language and item contains a @value entry, then set common language to @none because list items have conflicting languages.
        6. If common type is null, set it to item type.
        7. Otherwise, if item type does not equal common type, then set common type to @none because list items have conflicting types.
        8. If common language is @none and common type is @none, then stop processing items in the list because it has been detected that there is no common language or type amongst the items.
      5. If common language is null, set it to @none.
      6. If common type is null, set it to @none.
      7. If common type is not @none then set type/language to @type and type/language value to common type.
      8. Otherwise, set type/language value to common language.
    8. Otherwise, if value is a graph object, prefer a mapping most appropriate for the particular value.
      1. If value contains an @index entry, append the values @graph@index and @graph@index@set to containers.
      2. If the value contains an @id entry, append the values @graph@id and @graph@id@set to containers.
      3. Append the values @graph @graph@set, and @set to containers.
      4. If value does not contain an @index entry, append the values @graph@index and @graph@index@set to containers.
      5. If the value does not contain an @id entry, append the values @graph@id and @graph@id@set to containers.
      6. Append the values @index and @index@set to containers.
      7. Set type/language to @type and set type/language value to @id.
    9. Otherwise:
      1. If value is a value object:
        1. If value contains an @language entry and does not contain an @index entry, then set type/language value to its associated value and, append @language and @language@set to containers.
        2. Otherwise, if value contains a @type entry, then set type/language value to its associated value and set type/language to @type.
      2. Otherwise, set type/language to @type and set type/language value to @id, and append @id, @id@set, @type, and @set@type, to containers.
      3. Append @set to containers.
    10. Append @none to containers. This represents the non-existence of a container mapping, and it will be the last container mapping value to be checked as it is the most generic.
    11. If processing mode is json-ld-1.1 and value does not contain an @index entry, append @index and @index@set to containers.
    12. If processing mode is json-ld-1.1 and value contains only an @value entry, append @language and @language@set to containers.
    13. If type/language value is null, set it to @null. This is the key under which null values are stored in the inverse context entry.
    14. Initialize preferred values to an empty array. This array will indicate, in order, the preferred values for a term's type mapping or language mapping.
    15. If type/language value is @reverse, append @reverse to preferred values.
    16. If type/language value is @id or @reverse and value has an @id entry:
      1. If the result of using the IRI compaction algorithm, passing active context, inverse context, the value associated with the @id entry in value for var, and true for vocab has a term definition in the active context with an IRI mapping that equals the value associated with the @id entry in value, then append @vocab, @id, and @none, in that order, to preferred values.
      2. Otherwise, append @id, @vocab, and @none, in that order, to preferred values.
    17. Otherwise, append type/language value and @none, in that order, to preferred values. If value is an empty list object, set type/language to @any.
    18. Append @any to preferred values.
    19. Initialize term to the result of the Term Selection algorithm, passing inverse context, var, containers, type/language, and preferred values.
    20. If term is not null, return term.
  3. At this point, there is no simple term that var can be compacted to. If vocab is true and active context has a vocabulary mapping:
    1. If var begins with the vocabulary mapping's value but is longer, then initialize suffix to the substring of var that does not match. If suffix does not have a term definition in active context, then return suffix.
  4. The var could not be compacted using the active context's vocabulary mapping. Try to create a compact IRI, starting by initializing compact IRI to null. This variable will be used to store the created compact IRI, if any.
  5. For each key term and value term definition in the active context:
    1. If the term definition is null, its IRI mapping equals var, its IRI mapping is not a substring at the beginning of var, or the term definition does not contain the prefix flag having a value of true, the term cannot be used as a prefix. Continue with the next term.
    2. Initialize candidate by concatenating term, a colon (:), and the substring of var that follows after the value of the term definition's IRI mapping.
    3. If either compact IRI is null, candidate is shorter or the same length but lexicographically less than compact IRI and candidate does not have a term definition in active context, or if the term definition has an IRI mapping that equals var and value is null, set compact IRI to candidate.
  6. If compact IRI is not null, return compact IRI.
  7. To ensure that the absolute IRI var is not confused with a compact IRI, if the IRI scheme of var matches any term in active context with prefix flag set to true, and var has no IRI authority (beginning with double-forward-slash (//), an IRI confused with prefix error has been detected, and processing is aborted.
  8. If vocab is false, transform var to a relative IRI using the base IRI from active context, if it exists.
  9. Finally, return var as is.

6.4 Term Selection

This algorithm, invoked via the IRI Compaction algorithm, makes use of an active context's inverse context to find the term that is best used to compact an IRI. Other information about a value associated with the IRI is given, including which container mapping and which type mapping or language mapping would be best used to express the value.

6.4.1 Overview

This section is non-normative.

The inverse context's entry for the IRI will be first searched according to the preferred container mapping, in the order that they are given. Amongst terms with a matching container mapping, preference will be given to those with a matching type mapping or language mapping, over those without a type mapping or language mapping. If there is no term with a matching container mapping then the term without a container mapping that matches the given type mapping or language mapping is selected. If there is still no selected term, then a term with no type mapping or language mapping will be selected if available. No term will be selected that has a conflicting type mapping or language mapping. Ties between terms that have the same mappings are resolved by first choosing the shortest terms, and then by choosing the lexicographically least term. Note that these ties are resolved automatically because they were previously resolved when the Inverse Context Creation algorithm was used to create the inverse context.

6.4.2 Algorithm

This algorithm has five required inputs. They are: an inverse context, a keyword or IRI var, an array containers that represents an ordered list of preferred container mapping, a string type/language that indicates whether to look for a term with a matching type mapping or language mapping, and an array representing an ordered list of preferred values for the type mapping or language mapping to look for.

  1. Initialize container map to the value associated with var in the inverse context.
  2. For each item container in containers:
    1. If container is not a entry of container map, then there is no term with a matching container mapping for it, so continue to the next container.
    2. Initialize type/language map to the value associated with the container entry in container map.
    3. Initialize value map to the value associated with type/language entry in type/language map.
    4. For each item in preferred values:
      1. If item is not a entry of value map, then there is no term with a matching type mapping or language mapping, so continue to the next item.
      2. Otherwise, a matching term has been found, return the value associated with the item entry in value map.
  3. No matching term has been found. Return null.

6.4.3 Examples

This section is non-normative.

The following examples are intended to illustrate how the term selection algorithm behaves for different term definitions and values. It is not comprehensive, but intended to illustrate different parts of the algorithm.

Language Map Term

If the term definition has "@container": "@language", it will only match a value object having no @type.

Datatyped Term

If the term definition has a datatype, it will only match a value object having a matching datatype.

6.5 Value Compaction

Expansion transforms all values into expanded form in JSON-LD. This algorithm performs the opposite operation, transforming a value into compacted form. This algorithm compacts a value according to the term definition in the given active context that is associated with the value's associated active property.

6.5.1 Overview

This section is non-normative.

The value to compact has either an @id or an @value entry.

For the former case, if the type mapping of active property is set to @id or @vocab and value consists of only an @id entry and, if the container mapping of active property includes @index, an @index entry, value can be compacted to a string by returning the result of using the IRI Compaction algorithm to compact the value associated with the @id entry. Otherwise, value cannot be compacted and is returned as is.

For the latter case, it might be possible to compact value just into the value associated with the @value entry. This can be done if the active property has a matching type mapping or language mapping and there is either no @index entry or the container mapping of active property includes @index. It can also be done if @value is the only entry in value (apart an @index entry in case the container mapping of active property includes @index) and either its associated value is not a string, there is no default language, or there is an explicit null language mapping for the active property.

6.5.2 Algorithm

This algorithm has four required inputs: an active context, an inverse context, an active property, and a value to be compacted.

  1. Initialize number entries to the number of entries value contains.
  2. If value has an @index entry and the container mapping associated to active property includes @index, decrease number entries by 1.
  3. If number entries is greater than 2, return value as it cannot be compacted.
  4. If the type mapping of active property is @none, leave value as is, as value compaction is disabled.
    1. Replace any value of @type in value with the result of using the IRI compaction algorithm, passing active context, inverse context, the value of the @type entry for var, and true for vocab.
    2. Replace each key in value with the result of using the IRI compaction algorithm, passing active context, inverse context, the that key for var, and true for vocab.
    3. Return value.
  5. If value has an @id entry:
    1. If number entries is 1 and the type mapping of active property is set to @id, return the result of using the IRI compaction algorithm, passing active context, inverse context, and the value of the @id entry for var.
    2. Otherwise, if number entries is 1 and the type mapping of active property is set to @vocab, return the result of using the IRI compaction algorithm, passing active context, inverse context, the value of the @id entry for var, and true for vocab.
    3. Otherwise, return value as is.
  6. Otherwise, if value has an @type entry whose value matches the type mapping of active property, return the value associated with the @value entry of value.
  7. Otherwise, if value has an @language entry whose value matches the language mapping of active property, return the value associated with the @value entry of value.
  8. Otherwise, if number entries equals 1 and either the value of the @value entry is not a string, or the active context has no default language, or the language mapping of active property is set to null, return the value associated with the @value entry.
  9. Otherwise:
    1. Replace any value of @type in value with the result of using the IRI compaction algorithm, passing active context, inverse context, the value of the @type entry for var, and true for vocab.
    2. Replace each key in value with the result of using the IRI compaction algorithm, passing active context, inverse context, the that key for var, and true for vocab.
    3. Return value.

7. Flattening Algorithms

7.1 Flattening Algorithm

This algorithm flattens an expanded JSON-LD document by collecting all properties of a node in a single map and labeling all blank nodes with blank node identifiers. This resulting uniform shape of the document, may drastically simplify the code required to process JSON-LD data in certain applications.

7.1.1 Overview

This section is non-normative.

First, a node map is generated using the Node Map Generation algorithm which collects all properties of a node in a single map. In the next step, the node map is converted to a JSON-LD document in flattened document form. Finally, if a context has been passed, the flattened document is compacted using the Compaction algorithm before being returned.

7.1.2 Algorithm

The algorithm takes one required and two optional input variables. The required input is an element to flatten. The optional inputs are the context used to compact the flattened document and the ordered flag, used to order map entry keys lexicographically, where noted. If not passed, context is set to null and, the ordered flag is set to false.

This algorithm uses the Generate Blank Node Identifier algorithm to generate new blank node identifiers and relabel existing blank node identifiers. The Generate Blank Node Identifier algorithm maintains an identifier map to ensure that blank node identifiers in the source document are consistently remapped to new blank node identifiers avoiding collisions. Thus, before this algorithm is run, the identifier map is reset.

  1. Initialize node map to a map consisting of a single entry whose key is @default and whose value is an empty map.
  2. Perform the Node Map Generation algorithm, passing element and node map.
  3. Initialize default graph to the value of the @default entry of node map, which is a map representing the default graph.
  4. For each key-value pair graph name-graph in node map where graph name is not @default, ordered lexicographically by graph name if ordered is true, perform the following steps:
    1. If default graph does not have a graph name entry, create one and initialize its value to a map consisting of an @id entry whose value is set to graph name.
    2. Reference the value associated with the graph name entry in default graph using the variable entry.
    3. Add an @graph entry to entry and set it to an empty array.
    4. For each id-node pair in graph ordered lexicographically by id if ordered is true, add node to the @graph entry of entry, unless the only entry of node is @id.
  5. Initialize an empty array flattened.
  6. For each id-node pair in default graph ordered lexicographically by id if ordered is true, add node to flattened, unless the only entry of node is @id.
  7. If context is null, return flattened.
  8. Otherwise, return the result of compacting flattened according the Compaction algorithm passing context and the ordered flag ensuring that the compaction result has only the @graph keyword (or its alias) at the top-level other than @context, 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.

7.2 Node Map Generation

This algorithm creates a map node map 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 node map will have an map entry for every graph in the document whose value is another object with a entry for every node represented in the document. The default graph is stored under the @default entry, all other graphs are stored under their graph name.

7.2.1 Overview

This section is non-normative.

The algorithm recursively runs over an expanded JSON-LD document to collect all entries of a node in a single map. The algorithm updates a map node map whose keys represent the graph names used in the document (the default graph is stored under the @default entry) and whose associated values are maps which index the nodes in the graph. If a entry's value is a node object, it is replaced by a node object consisting of only an @id entry. If a node object has no @id entry or it is identified by a blank node identifier, a new blank node identifier is generated. This relabeling of blank node identifiers is also done for properties and values of @type.

7.2.2 Algorithm

The algorithm takes as input an expanded JSON-LD document element and a reference to a map node map. Furthermore it has the optional parameters active graph (which defaults to @default), an active subject, active property, and a reference to a map list. If not passed, active subject, active property, and list are set to null.

  1. If element is an array, process each item in element as follows and then return:
    1. Run this algorithm recursively by passing item for element, node map, active graph, active subject, active property, and list.
  2. Otherwise element is a map. Reference the map which is the value of the active graph entry of node map using the variable graph. If the active subject is null, set node to null otherwise reference the active subject entry of graph using the variable subject node.
  3. If element has an @type entry, perform for each item the following steps:
    1. If item is a blank node identifier, replace it with a newly generated blank node identifier passing item for identifier.
  4. If element has an @value entry, perform the following steps:
    1. If list is null:
      1. If subject node does not have an active property entry, create one and initialize its value to an array containing element.
      2. Otherwise, compare element against every item in the array associated with the active property entry of subject node. If there is no item equivalent to element, append element to the array. Two maps are considered equal if they have equivalent map entries.
    2. Otherwise, append element to the @list entry of list.
  5. Otherwise, if element has an @list entry, perform the following steps:
    1. Initialize a new map result consisting of a single entry @list whose value is initialized to an empty array.
    2. Recursively call this algorithm passing the value of element's @list entry for element, node map, active graph, active subject, active property, and result for list.
    3. If list is null, append result to the value of the active property entry of subject node.
    4. Otherwise, append result to the @list entry of list.
  6. Otherwise element is a node object, perform the following steps:
    1. If element has an @id entry, set id to its value and remove the entry from element. If id is a blank node identifier, replace it with a newly generated blank node identifier passing id for identifier.
    2. Otherwise, set id to the result of the Generate Blank Node Identifier algorithm passing null for identifier.
    3. If graph does not contain a entry id, create one and initialize its value to a map consisting of a single entry @id whose value is id.
    4. Reference the value of the id entry of graph using the variable node.
    5. If active subject is a map, a reverse property relationship is being processed. Perform the following steps:
      1. If node does not have a active property entry, create one and initialize its value to an array containing active subject.
      2. Otherwise, compare active subject against every item in the array associated with the active property entry of node. If there is no item equivalent to active subject, append active subject to the array. Two maps are considered equal if they have equivalent map entries.
    6. Otherwise, if active property is not null, perform the following steps:
      1. Create a new map reference consisting of a single entry @id whose value is id.
      2. If list is null:
        1. If subject node does not have an active property entry, create one and initialize its value to an array containing reference.
        2. Otherwise, compare reference against every item in the array associated with the active property entry of subject node. If there is no item equivalent to reference, append reference to the array. Two maps are considered equal if they have equivalent map entries.
      3. Otherwise, append reference to the @list entry of list.
    7. If element has an @type entry, append each item of its associated array to the array associated with the @type entry of node unless it is already in that array. Finally remove the @type entry from element.
    8. If element has an @index entry, set the @index entry of node to its value. If node has already an @index entry with a different value, a conflicting indexes error has been detected and processing is aborted. Otherwise, continue by removing the @index entry from element.
    9. If element has an @reverse entry:
      1. Create a map referenced node with a single entry @id whose value is id.
      2. Set reverse map to the value of the @reverse entry of element.
      3. For each key-value pair property-values in reverse map:
        1. For each value of values:
          1. Recursively invoke this algorithm passing value for element, node map, active graph, referenced node for active subject, and property for active property. Passing a map for active subject indicates to the algorithm that a reverse property relationship is being processed.
      4. Remove the @reverse entry from element.
    10. If element has an @graph entry, recursively invoke this algorithm passing the value of the @graph entry for element, node map, and id for active graph before removing the @graph entry from element.
    11. If element has an @included entry, recursively invoke this algorithm passing the value of the `@included entry for element, node map, and active graph before removing the @included entry from element.
    12. Finally, for each key-value pair property-value in element ordered by property perform the following steps:
      1. If property is a blank node identifier, replace it with a newly generated blank node identifier passing property for identifier.
        (Feature at Risk) Issue
        The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD.
      2. If node does not have a property entry, create one and initialize its value to an empty array.
      3. Recursively invoke this algorithm passing value for element, node map, active graph, id for active subject, and property for active property.

7.3 Generate Blank Node Identifier

This algorithm is used to generate new blank node identifiers or to relabel an existing blank node identifier to avoid collision by the introduction of new ones.

7.3.1 Overview

This section is non-normative.

The simplest case is if there exists already a blank node identifier in the identifier map for the passed identifier, in which case it is simply returned. Otherwise, a new blank node identifier is generated. If the passed identifier is not null, an entry is created in the identifier map associating the identifier with the blank node identifier.

7.3.2 Algorithm

The algorithm takes a single input variable identifier which may be null. The algorithm maintains an identifier map to relabel existing blank node identifiers to new blank node identifiers, which is reset when the invoking algorithm is initialized.

  1. If identifier is not null and has an entry in the identifier map, return the mapped identifier.
  2. Otherwise, generate a new unique blank node identifier.
  3. If identifier is not null, create a new entry for identifier in identifier map and set its value to the new blank node identifier.
  4. Return the new blank node identifier.
Note

One way of generating new blank node identifiers is to maintain a counter and increment it when generating a new identifier and appending it to a string such as _:b.

7.4 Merge Node Maps

This algorithm creates a new map of subjects to nodes using all graphs contained in the graph map created using the Node Map Generation algorithm to create merged node objects containing information defined for a given subject in each graph contained in the node map.

  1. Create result as an empty map
  2. For each graph name and node map in graph map and for each id and node in node map:
    1. Set merged node to the value for id in result, initializing it with a new map consisting of a single entry @id whose value is id, if it does not exist.
    2. For each property and values in node:
      1. If property is a keyword, add property and values to merged node.
      2. Otherwise, merge each element from values into the values for property in merged node, initializing it to an empty array if necessary.
  3. Return result.

8. RDF Serialization/Deserialization Algorithms

This section describes algorithms to deserialize a JSON-LD document to an RDF dataset and vice versa. The algorithms are designed for in-memory implementations with random access to map elements.

8.1 Deserialize JSON-LD to RDF Algorithm

This algorithm deserializes a JSON-LD document to an RDF dataset. Please note that RDF does not allow a blank node to be used as a property, while JSON-LD does. Therefore, by default triples that would have contained blank nodes as properties are discarded when interpreting JSON-LD as RDF.

(Feature at Risk) Issue

The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD.

Implementations MUST generate only well-formed triples and graph names:

8.1.1 Overview

This section is non-normative.

The JSON-LD document is expanded and converted to a node map using the Node Map Generation algorithm. This allows each graph represented within the document to be extracted and flattened, making it easier to process each node object. Each graph from the node map is processed to extract triple, to which any (non-default) graph name is applied to create an RDF dataset. Each node object in the node map has an @id entry which corresponds to the subject, the other entries represent predicates. Each entry value is either an IRI or blank node identifier or can be transformed to anRDF literal to generate an triple. Lists are transformed into an RDF collection using the List to RDF Conversion algorithm.

8.1.2 Algorithm

The algorithm takes a map node map, which is the result of the Node Map Generation algorithm and an RDF dataset dataset into which new graphs and triples are added. Unless the produceGeneralizedRdf option is set to true, triple containing a blank node predicate are excluded from output.

(Feature at Risk) Issue

The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for generalized RDF Datasets and thus the produceGeneralizedRdf option may be also be removed.

  1. For each graph name and graph in node map ordered by graph name:
    1. If graph name is not well-formed, continue with the next graph name-graph pair.
    2. If graph name is @default, set set triples to the value of the defaultGraph attribute of dataset. Otherwise, initialize graph as an empty RdfGraph and add to dataset using its add method along with graph name for graphName.
    3. For each subject and node in graph ordered by subject:
      1. If subject is not well-formed, continue with the next subject-node pair.
      2. For each property and values in node ordered by property:
        1. If property is @type, then for each type in values, create a new RdfTriple composed of subject, rdf:type for predicate, and type for object and add to triples using its add method, unless type is not well-formed.
        2. Otherwise, if property is a keyword continue with the next property-values pair.
        3. Otherwise, if property is a blank node identifier and the produceGeneralizedRdf option is not true, continue with the next property-values pair.
          (Feature at Risk) Issue
          The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for generalized RDF Datasets and thus the produceGeneralizedRdf option may be also be removed.
        4. Otherwise, if property is not well-formed, continue with the next property-values pair.
        5. Otherwise, property is an absolute IRI or blank node identifier. For each item in values:
          1. item is a value object, list object, or a node object.
          2. Initialize list triples as an empty array.
          3. Append a triple composed of subject, property, and the result of using the Object to RDF Conversion algorithm passing item and list triples to triples, unless the result is null, indicating a non-well-formed resource that has to be ignored.
          4. Add all RdfTriple instances from list triples to triples using its using its add method.

8.2 Object to RDF Conversion

This algorithm takes a node object, list object, or value object and transforms it into an resource to be used as the object of an triple. If a node object containing a relative IRI is passed to the algorithm, null is returned which then causes the resulting triple to be ignored. If the input is a list object, it will also return the triples created from that input.

8.2.1 Overview

This section is non-normative.

Value objects are transformed to RDF literals as described in § 8.6 Data Round Tripping whereas node objects are transformed to IRIs, blank node identifiers, or null.

8.2.2 Algorithm

The algorithm takes as two arguments item which MUST be either a value object, list object, or node object and list triples, which is an empty array.

  1. If item is a node object and the value of its @id entry is not well-formed, return null.
  2. If item is a node object, return the IRI or blank node identifier associated with its @id entry.
  3. If item is a list object return the result of the List Conversion algorithm, passing the value associated with the @list entry from item and list triples.
  4. Otherwise, item is a value object. Initialize value to the value associated with the @value entry in item.
  5. Initialize datatype to the value associated with the @type entry of item or null if item does not have such a entry.
  6. If datatype is not well-formed, return null.
  7. If item has an @language entry which is not well-formed, return null.
  8. If datatype is @json, convert value to the canonical lexical form using the result of transforming the internal representation of value to JSON and set datatype to rdf:JSON.
    (Feature at Risk) Issue
    The JSON Canonicalization Scheme [JCS] is an emerging standard for JSON canonicalization not yet ready to be referenced. When a JSON canonicalization standard becomes available, this specification will likely be updated to require such a canonical representation. Users are cautioned from depending on the JSON literal lexical representation as an RDF literal, as the specifics of serialization may change in a future revison of this document.
  9. If value is true or false, set value to the string true or false which is the canonical lexical form as described in § 8.6 Data Round Tripping If datatype is null, set it to xsd:boolean.
  10. Otherwise, if value is a number with a non-zero fractional part (the result of a modulo‑1 operation) or value is a number and datatype equals xsd:double, convert value to a string in canonical lexical form of an xsd:double as defined in [XMLSCHEMA11-2] and described in § 8.6 Data Round Tripping. If datatype is null, set it to xsd:double.
  11. Otherwise, if value is a number with no non-zero fractional part (the result of a modulo‑1 operation) or value is a number and datatype equals xsd:integer, convert value to a string in canonical lexical form of an xsd:integer as defined in [XMLSCHEMA11-2] and described in § 8.6 Data Round Tripping. If datatype is null, set it to xsd:integer.
  12. Otherwise, if datatype is null, set it to xsd:string or rdf:langString, depending on if item has an @language entry.
  13. Initialize literal as an RDF literal using value and datatype. If item has an @language entry, add the value associated with the @language entry as the language tag of literal.
  14. Return literal.

8.3 List to RDF Conversion

List Conversion is the process of taking a list object and transforming it into an RDF collection as defined in RDF Semantics [RDF11-MT].

8.3.1 Overview

This section is non-normative.

For each element of the list a new blank node identifier is allocated which is used to generate rdf:first and rdf:rest. The algorithm returns the list head, which is either the first allocated blank node identifier or rdf:nil if the list is empty. If a list element represents a relative IRI, the corresponding rdf:first triple is omitted.

8.3.2 Algorithm

The algorithm takes two inputs: an array list and an empty array list triples used for returning the generated triples.

  1. If list is empty, return rdf:nil.
  2. Otherwise, create an array bnodes composed of a newly generated blank node identifier for each entry in list.
  3. For each pair of subject from bnodes and item from list:
    1. Initialize embedded triples to a new empty array.
    2. Initialize object to the result of using the Object to RDF Conversion algorithm passing item and embedded triples for list triples.
    3. Unless object is null, append a triple composed of subject, rdf:first, and object to list triples.
    4. Set rest as the next entry in bnodes, or if that does not exist, rdf:nil. Append a triple composed of subject, rdf:rest, and rest to list triples.
    5. Append all values from embedded triples to list triples
  4. Return the first blank node from bnodes or rdf:nil if bnodes is empty.

8.4 Serialize RDF as JSON-LD Algorithm

This algorithm serializes an RDF dataset consisting of a default graph and zero or more named graphs into a JSON-LD document.

In the RDF abstract syntax, RDF literals have a lexical form, as defined in [RDF11-CONCEPTS]. The form of these literals is used when creating JSON-LD values based on these literals.

8.4.1 Overview

This section is non-normative.

Iterate through each graph in the dataset, converting each RDF collection into a list and generating a JSON-LD document in expanded form for all RDF literals, IRIs and blank node identifiers. If the useNativeTypes flag is set to true, RDF literals with a datatype IRI that equals xsd:integer or xsd:double are converted to a JSON numbers and RDF literals with a datatype IRI that equals xsd:boolean are converted to true or false based on their lexical form as described in § 8.6 Data Round Tripping. Unless the useRdfType flag is set to true, rdf:type predicates will be serialized as @type as long as the associated object is either an IRI or blank node identifier.

8.4.2 Algorithm

The algorithm takes one required and three optional inputs: an RDF dataset dataset and the three flags useNativeTypes, useRdfType, and the ordered flag, used to order map entry keys lexicographically, where noted that all default to false.

The dataset is iterable to iterate over graphs and graph names contained within the RdfDataset. Each graph is also iterable for iterating over triples contained within the RdfGraph.

  1. Initialize default graph to an empty map.
  2. Initialize graph map to a map consisting of a single entry @default whose value references default graph.
  3. Initialize referenced once to an empty map.
  4. For each graph in dataset:
    1. If graph is the default graph, set name to @default, otherwise to the graph name associated with graph.
    2. If graph map has no name entry, create one and set its value to an empty map.
    3. If graph is not the default graph and default graph does not have a name entry, create such a entry and initialize its value to a new map with a single entry @id whose value is name.
    4. Reference the value of the name entry in graph map using the variable node map.
    5. For each triple in graph consisting of subject, predicate, and object:
      1. If node map does not have a subject entry, create one and initialize its value to a new map consisting of a single entry @id whose value is set to subject.
      2. Reference the value of the subject entry in node map using the variable node.
      3. If object is an IRI or blank node identifier, and node map does not have an object entry, create one and initialize its value to a new map consisting of a single entry @id whose value is set to object.
      4. If predicate equals rdf:type, the useRdfType flag is not true, and object is an IRI or blank node identifier, append object to the value of the @type entry of node; unless such an item already exists. If no such entry exists, create one and initialize it to an array whose only item is object. Finally, continue to the next triple.
      5. Set value to the result of using the RDF to Object Conversion algorithm, passing object and useNativeTypes.
      6. If node does not have a predicate entry, create one and initialize its value to an empty array.
      7. If there is no item equivalent to value in the array associated with the predicate entry of node, append a reference to value to the array. Two maps are considered equal if they have equivalent map entries.
      8. If object is rdf:nil, it represents the termination of an RDF collection:
        1. Reference the usages entry of the object entry of node map using the variable usages.
        2. Append a new map consisting of three entries, node, property, and value to the usages array. The node entry is set to a reference to node, property to predicate, and value to a reference to value.
      9. Otherwise, if referenced once has an entry for object, set the object entry of referenced once to false.
      10. Otherwise, if object is a blank node identifier, it might represent a list node:
        1. Set the object entry of referenced once to a new map consisting of three entries, node, property, and value to the usages array. The node entry is set to a reference to node, property to predicate, and value to a reference to value.
  5. For each name and graph object in graph map:
    1. If graph object has no rdf:nil entry, continue with the next name-graph object pair as the graph does not contain any lists that need to be converted.
    2. Initialize nil to the value of the rdf:nil entry of graph object.
    3. For each item usage in the usages entry of nil, perform the following steps:
      1. Initialize node to the value of the value of the node entry of usage, property to the value of the property entry of usage, and head to the value of the value entry of usage.
      2. Initialize two empty arrays list and list nodes.
      3. While property equals rdf:rest, the value of the @id entry of node is a blank node identifier, the value of the entry of referenced once associated with the @id entry of node is a map, node has rdf:first and rdf:rest entries, both of which have as value an array consisting of a single element, and node has no other entries apart from an optional @type entry whose value is an array with a single item equal to rdf:List, node represents a well-formed list node. Perform the following steps to traverse the list backwards towards its head:
        1. Append the only item of rdf:first entry of node to the list array.
        2. Append the value of the @id entry of node to the list nodes array.
        3. Initialize node usage to the value of the entry of referenced once associated with the @id entry of node.
        4. Set node to the value of the node entry of node usage, property to the value of the property entry of node usage, and head to the value of the value entry of node usage.
        5. If the @id entry of node is an IRI instead of a blank node identifier, exit the while loop.
      4. Remove the @id entry from head.
      5. Reverse the order of the list array.
      6. Add an @list entry to head and initialize its value to the list array.
      7. For each item node id in list nodes, remove the node id entry from graph object.
  6. Initialize an empty array result.
  7. For each subject and node in default graph ordered lexicographically by subject if ordered is true:
    1. If graph map has a subject entry:
      1. Add an @graph entry to node and initialize its value to an empty array.
      2. For each key-value pair s-n in the subject entry of graph map ordered lexicographically by s if ordered is true, append n to the @graph entry of node after removing its usages entry, unless the only remaining entry of n is @id.
    2. Append node to result after removing its usages entry, unless the only remaining entry of node is @id.
  8. Return result.

8.5 RDF to Object Conversion

This algorithm transforms an RDF literal to a JSON-LD value object and a RDF blank node or IRI to an JSON-LD node object.

8.5.1 Overview

This section is non-normative.

RDF literals are transformed to value objects whereas IRIs and blank node identifiers are transformed to node objects. Literals with datatype rdf:JSON are transformed into a value object using the internal representation based on the lexical-to-value mapping defined in JSON datatype in [JSON-LD11], and @type of @json. If the useNativeTypes flag is set to true, RDF literals with a datatype IRI that equals xsd:integer or xsd:double are converted to a JSON numbers and RDF literals with a datatype IRI that equals xsd:boolean are converted to true or false based on their lexical form as described in § 8.6 Data Round Tripping.

8.5.2 Algorithm

This algorithm takes two required inputs: a value to be converted to a map and a flag useNativeTypes.

  1. If value is an IRI or a blank node identifier, return a new map consisting of a single entry @id whose value is set to value.
  2. Otherwise value is an RDF literal:
    1. Initialize a new empty map result.
    2. Initialize converted value to value.
    3. Initialize type to null
    4. If useNativeTypes is true
      1. If the datatype IRI of value equals xsd:string, set converted value to the lexical form of value.
      2. Otherwise, if the datatype IRI of value equals xsd:boolean, set converted value to true if the lexical form of value matches true, or false if it matches false. If it matches neither, set type to xsd:boolean.
      3. Otherwise, if the datatype IRI of value equals xsd:integer or xsd:double and its lexical form is a valid xsd:integer or xsd:double according [XMLSCHEMA11-2], set converted value to the result of converting the lexical form to a JSON number.
    5. Otherwise, if processing mode is json-ld-1.1, and value is a JSON literal, set the @value entry to the result of turning the lexical value of value into the JSON-LD internal representation, and set type to @json.
    6. Otherwise, if value is a language-tagged string add a entry @language to result and set its value to the language tag of value.
    7. Otherwise, set type to the datatype IRI of value, unless it equals xsd:string which is ignored.
    8. Add a entry @value to result whose value is set to converted value.
    9. If type is not null, add a entry @type to result whose value is set to type.
    10. Return result.

8.6 Data Round Tripping

When deserializing JSON-LD to RDF JSON-native numbers are automatically type-coerced to xsd:integer or xsd:double depending on whether the number has a non-zero fractional part or not (the result of a modulo‑1 operation), the boolean values true and false are coerced to xsd:boolean, and strings are coerced to xsd:string. The JSON, numeric, or boolean values themselves are converted to canonical lexical form, i.e., a deterministic string representation as defined in [XMLSCHEMA11-2].

The canonical lexical form of an integer, i.e., a number with no non-zero fractional part and an exponent less than 21, or a number coerced to xsd:integer, is a finite-length sequence of decimal digits (0-9) with an optional leading minus sign; leading zeros are prohibited. In JavaScript, implementers can use the following snippet of code to convert an integer to canonical lexical form:

Example 20: Sample integer serialization implementation in JavaScript
(value).toFixed(0).toString()

The canonical lexical form of a double, i.e., a number which cannot be represented as an integer, or a number coerced to xsd:double, consists of a mantissa followed by the character E, followed by an exponent. The mantissa is a decimal number and the exponent is an integer. Leading zeros and a preceding plus sign (+) are prohibited in the exponent. If the exponent is zero, it is indicated by E0. For the mantissa, the preceding optional plus sign is prohibited and the decimal point is required. Leading and trailing zeros 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-2008] whereas the value space of JSON numbers is not specified; when deserializing JSON-LD to RDF the mantissa is rounded to 15 digits after the decimal point. In JavaScript, implementers can use the following snippet of code to convert a double to canonical lexical form:

Example 21: Sample floating point number serialization implementation in JavaScript
(value).toExponential(15).replace(/(\d)0*e\+?/,'$1E')

The canonical lexical form of the boolean values true and false are the strings true and false.

The canonical lexical form of a JSON literal value is non-normative, as a normative recommendation for JSON canonicalization is not yet defined. Implementations SHOULD use the following guidelines when creating the lexical representation of a JSON literal:

(Feature at Risk) Issue

The JSON Canonicalization Scheme [JCS] is an emerging standard for JSON canonicalization not yet ready to be referenced. When a JSON canonicalization standard becomes available, this specification will likely be updated to require such a canonical representation. Users are cautioned from depending on the JSON literal lexical representation as an RDF literal, as the specifics of serialization may change in a future revison of this document.

When JSON-native numbers are deserialized to RDF, lossless data round-tripping cannot be guaranteed, as rounding errors might occur. When serializing RDF as JSON-LD, similar rounding errors might occur. Furthermore, the datatype or the lexical representation might be lost. An xsd:double with a value of 2.0 will, e.g., result in an xsd:integer with a value of 2 in canonical lexical form when converted from RDF to JSON-LD and back to RDF. It is important to highlight that in practice it might be impossible to losslessly convert an xsd:integer to a number because its value space is not limited. While the JSON specification [RFC8259] does not limit the value space of numbers either, concrete implementations typically do have a limited value space.

To ensure lossless round-tripping the Serialize RDF as JSON-LD Algorithm specifies a useNativeTypes flag which controls whether RDF literals with a datatype IRI equal to xsd:integer, xsd:double, or xsd:boolean are converted to their JSON-native counterparts. If the useNativeTypes flag is set to false, all literals remain in their original string representation.

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, forward slashes MUST NOT be backslash-escaped.

9. HTML Content Algorithms

Note

This section describes features required of a full Processor.

9.1 Extract Script Content Algorithm

The algorithm extracts the text content a JSON-LD script element into a map or array of maps. A JSON-LD script element is a script element within an HTML [HTML] document with the type attribute set to application/ld+json.

The algorithm takes a single required input variable: source, the textContent of an HTML script element.

  1. If source is not a valid JSON document, an invalid script element has been detected, and processing is aborted.
  2. Return the result of transforming source into the internal representation.

10. The Application Programming Interface

This API provides a clean mechanism that enables developers to convert JSON-LD data into a variety of output formats that are often easier to work with.

The JSON-LD API uses Promises to represent the result of the various asynchronous operations. Promises are defined in [ECMASCRIPT]. General use within specifications can be found in [promises-guide].

10.1 The JsonLdProcessor Interface

The JsonLdProcessor interface is the high-level programming structure that developers use to access the JSON-LD transformation methods.

It is important to highlight that implementations do not modify the input parameters. If an error is detected, the Promise is rejected passing a JsonLdError with the corresponding error code and processing is stopped.

If the documentLoader option is specified, it is used to dereference remote documents and contexts. The documentUrl in the returned RemoteDocument is used as base IRI and the contextUrl is used instead of looking at the HTTP Link Header directly. For the sake of simplicity, none of the algorithms in this document mention this directly.

[Exposed=Window]
interface JsonLdProcessor {
  static Promise<JsonLdDictionary> compact(
    JsonLdInput input,
    optional JsonLdContext context = {},
    optional JsonLdOptions options = {});
  static Promise<sequence<JsonLdDictionary>> expand(
    JsonLdInput input,
    optional JsonLdOptions options = {});
  static Promise<JsonLdDictionary> flatten(
    JsonLdInput input,
    optional JsonLdContext context = {},
    optional JsonLdOptions options = {});
  static Promise<sequence<JsonLdDictionary>> fromRdf(
    RdfDataset input,
    optional JsonLdOptions options = {});
  static Promise<RdfDataset> toRdf(
    JsonLdInput input,
    optional JsonLdOptions options = {});
};
compact()

Compacts the given input using the context according to the steps in the Compaction algorithm:

  1. Create a new Promise promise and return it. The following steps are then executed asynchronously.
  2. Set expanded input to the result of using the expand() method using input and options, with ordered set to false, and extractAllScripts defaulting to false.
  3. If context is a map having an @context entry, set context to that entry's value, otherwise to context.
  4. Initialize an active context using context; the base IRI is set to the base option from options, if set; otherwise, if the compactToRelative option is true, to the IRI of the currently being processed document, if available; otherwise to null.
  5. Set compacted output to the result of using the Compaction algorithm, using active context, an empty map as inverse context, null as property, expanded input as element, and if passed, the compactArrays and ordered flags in options.
  6. Resolve the promise with compacted output transforming compacted output from the internal representation to a JSON serialization.
input
The map, array of maps to perform the compaction upon, or an IRI referencing the JSON-LD document to compact.
context
The context to use when compacting the input; it can be specified by using a map, an IRI, or an array consisting of maps and IRIs.
options
A set of options to configure the algorithms. This allows, e.g., to set the input document's base IRI.
expand()

Expands the given input according to the steps in the Expansion algorithm:

  1. Create a new Promise promise and return it. The following steps are then executed asynchronously.
  2. If the passed input is a string representing the IRI of a remote document, await and dereference it as remote document using LoadDocumentCallback, passing input for url, the extractAllScripts option for extractAllScripts.
  3. If document from remote document is a string, transform into the internal representation. If document cannot be transformed to the internal representation, reject promise passing a loading document failed error.
  4. Initialize a new empty active context. The base IRI of the active context is set to the documentUrl from remote document, if available; otherwise to null. If set, the base option from options overrides the base IRI.
  5. If an expandContext option has been passed, update the active context using the Context Processing algorithm, passing the expandContext as local context. If expandContext is a map having an @context entry, pass that entry's value instead.
  6. If remote document has a contextUrl, update the active context using the Context Processing algorithm, passing the contextUrl as local context.
  7. Set expanded output to the result of using the Expansion algorithm, passing the active context and document from remote document, or input if there is no remote document as element, and if passed, the frameExpansion and ordered flags in options.
  8. Resolve the promise with expanded output transforming expanded output from the internal representation to a JSON serialization.
input
The map, or array of maps to perform the expansion upon, or an IRI referencing the JSON-LD document to expand.
options
A set of options to configure the used algorithms. This allows, e.g., to set the input document's base IRI.
flatten()

Flattens the given input and compacts it using the passed context according to the steps in the Flattening algorithm:

  1. Create a new Promise promise and return it. The following steps are then executed asynchronously.
  2. Set expanded input to the result of using the expand() method using input and options with ordered set to false, and extractAllScripts defaulting to true.
  3. If context is a map having an @context entry, set context to that entry's value, otherwise to context.
  4. Initialize an active context using context; the base IRI is set to the base option from options, if set; otherwise, if the compactToRelative option is true, to the IRI of the currently being processed document, if available; otherwise to null.
  5. Initialize an empty identifier map.
  6. Set flattened output to the result of using the Flattening algorithm, passing expanded input as element, active context, and if passed, the compactArrays and ordered flags in options.
  7. Resolve the promise with flattened output transforming flattened output from the internal representation to a JSON serialization.
input
The map, or array of maps, or an IRI referencing the JSON-LD document to flatten.
context
The context to use when compacting the flattened expanded input; it can be specified by using a map, an IRI, or an array consisting of maps and IRIs. If not passed or null is passed, the result will not be compacted but kept in expanded form.
options
A set of options to configure the used algorithms. This allows, e.g., to set the input document's base IRI.
fromRdf()

Transforms the given input into a JSON-LD document in expanded form according to the steps in the Serialize RDF as JSON-LD Algorithm:

Note

This interface does not define a means of creating an RdfDataset from an arbitrary input, other than the toRdf() method.

  1. Create a new Promise promise and return it. The following steps are then executed asynchronously.
  2. Set expanded result to the result of invoking the Serialize RDF as JSON-LD Algorithm method using dataset and options.
  3. Resolve the promise with expanded result transforming expanded result from the internal representation to a JSON serialization.
input
The map, or array of maps, or an IRI referencing the JSON-LD document to flatten.
options
A set of options to configure the used algorithms. This allows, e.g., to set the input document's base IRI.
toRdf()

Transforms the given input into an RdfDataset according to the steps in the Deserialize JSON-LD to RDF Algorithm:

  1. Create a new Promise promise and return it. The following steps are then executed asynchronously.
  2. Set expanded input to the result of using the expand() method using input and options with ordered set to false, and extractAllScripts defaulting to true.
  3. Create a new RdfDataset dataset.
  4. Create a new map node map.
  5. Invoke the Node Map Generation algorithm, passing expanded input as element and node map.
  6. Invoke the Deserialize JSON-LD to RDF Algorithm passing node map, dataset, and if passed, the produceGeneralizedRdf flag in options.
    (Feature at Risk) Issue
    The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for generalized RDF Datasets and thus the produceGeneralizedRdf option may be also be removed.
  7. Resolve the promise with dataset.
input
The map, or array of maps, or an IRI referencing the JSON-LD document to flatten.
options
A set of options to configure the used algorithms. This allows, e.g., to set the input document's base IRI.
dictionary JsonLdDictionary {};

The JsonLdDictionary is the definition of a map used to contain arbitrary map entries which are the result of parsing a JSON Object.

typedef (JsonLdDictionary or sequence<JsonLdDictionary> or USVString) JsonLdInput;

The JsonLdInput type is used to refer to an input value that that may be a map, an array of maps , or a string representing an IRI which can be dereferenced to retrieve a valid JSON document.

typedef (JsonLdDictionary or USVString or sequence<(JsonLdDictionary or USVString)>) JsonLdContext;

The JsonLdContext type is used to refer to a value that may be a map, a string representing an IRI, or an array of maps and strings.

10.2 RDF Dataset Interfaces

The RdfDataset interface describes operations on an RDF dataset used by the fromRdf() and toRdf() methods in the JsonLdProcessor interface. The interface may be used for constructing a new RDF dataset, which has a default graph accessible via the defaultGraph attribute.

[Constructor, Exposed=Window]
interface RdfDataset {
  readonly attribute RdfGraph defaultGraph;
  void add(USVString graphName, RdfGraph graph);
  iterable<USVString?, RdfGraph>;
};
add()

Adds an RdfGraph and its associated graph name to the RdfDataset. Used by the Deserialize JSON-LD to RDF Algorithm.

graphName
The graph name associated with graph. graphName MUST be a well-formed IRI or blank node identifier.
graph
The RdfGraph to add to the RdfDataset.
defaultGraph
Provides access to the default graph associated with the RDF dataset.
iterable
The value pairs to iterate over are the list of graph name-graph pairs, with the graph name being null (for the default graph), an IRI, or blank node identifier and graph an RdfGraph instance.

The RdfGraph interface describes operations on an RDF graph used by the fromRdf() and toRdf() methods in the JsonLdProcessor interface. The interface may be used for constructing a new RDF graph, which is composed of zero or more RdfTriple instances.

[Constructor, Exposed=Window]
interface RdfGraph {
  void add(RdfTriple triple);
  iterable<RdfTriple>;
};
add()

Adds an RdfTriple to the RdfGraph. Used by the Deserialize JSON-LD to RDF Algorithm.

triple
The RdfTriple to add to the RdfGraph.
iterable
A value iterator over the RdfTriple instances associated with the graph. Note that a given RdfTriple instance may appear in more than one graph within a particular RdfDataset instance.

The RdfTriple interface describes an triple.

[Constructor, Exposed=Window]
interface RdfTriple {
  readonly attribute USVString subject;
  readonly attribute USVString predicate;
  readonly attribute (USVString or RdfLiteral) object;
};
subject
An absolute IRI or blank node identifier denoting the subject of the triple.
predicate
An absolute IRI denoting the predicate of the triple. If used to represent a Generalized RDF Dataset, it may also be a blank node identifier.
(Feature at Risk) Issue
The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for generalized RDF Datasets.
object
An absolute IRI, blank node identifier, or literal denoting the object of the triple.

The RdfLiteral interface describes an RDF Literal.

[Constructor, Exposed=Window]
interface RdfLiteral {
  readonly attribute USVString value;
  readonly attribute USVString datatype;
  readonly attribute USVString? language;
};
value
The lexical value of the literal.
datatype
An absolute IRI denoting the datatype IRI of the literal. If the value is rdf:langString, language MUST be specified.
language
An optional language tag as defined by [BCP47]. If this value is specified, datatype MUST be rdf:langString.

10.3 The JsonLdOptions Type

The JsonLdOptions type is used to pass various options to the JsonLdProcessor methods.

dictionary JsonLdOptions {
  USVString?             base;
  boolean                compactArrays = true;
  boolean                compactToRelative = true;
  LoadDocumentCallback   documentLoader = null;
  (JsonLdDictionary? or USVString) expandContext = null;
  boolean                extractAllScripts = false;
  boolean                frameExpansion = false;
  boolean                ordered = false;
  USVString              processingMode = null;
  boolean                produceGeneralizedRdf = true;
  boolean                useNativeTypes = false;
  boolean                useRdfType = false;
};
base
The base IRI to use when expanding or compacting the document. If set, this overrides the input document's IRI.
compactArrays
If set to true, 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.
compactToRelative
Determines if IRIs are compacted relative to the base option or document location when compacting.
documentLoader
The callback of the loader to be used to retrieve remote documents and contexts, implementing the LoadDocumentCallback. If specified, it is used to retrieve remote documents and contexts; otherwise, if not specified, the processor's built-in loader is used.
expandContext
A context that is used to initialize the active context when expanding a document.
extractAllScripts
If set to true, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary.
frameExpansion
Enables special frame processing rules for the Expansion Algorithm.
Enables special rules for the Serialize RDF as JSON-LD Algorithm to use JSON-LD native types as values, where possible.
ordered
If set to true, certain algorithm processing steps where indicated are ordered lexicographically. If false, order is not considered in processing.
processingMode
Sets the processing mode. If set to json-ld-1.0 or json-ld-1.1, the implementation must produce exactly the same results as the algorithms defined in this specification. If set to another value, the JSON-LD processor is allowed to extend or modify the algorithms defined in this specification to enable application-specific optimizations. The definition of such optimizations is beyond the scope of this specification and thus not defined. Consequently, different implementations may implement different optimizations. Developers must not define modes beginning with json-ld as they are reserved for future versions of this specification.
produceGeneralizedRdf
If set to true, the JSON-LD processor may emit blank nodes for triple predicates, otherwise they will be omitted. Generalized RDF Datasets are defined in [RDF11-CONCEPTS].
(Feature at Risk) Issue
The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for generalized RDF Datasets and thus the produceGeneralizedRdf option may be also be removed.
useNativeTypes
Causes the Serialize RDF as JSON-LD Algorithm to use native JSON values in value objects avoiding the need for an explicitly @type.
useRdfType
Enables special rules for the Serialize RDF as JSON-LD Algorithm causing rdf:type properties to be kept as IRIs in the output, rather than use @type.

10.4 Remote Document and Context Retrieval

Users of an API implementation can utilize a callback to control how remote documents and contexts are retrieved. This section details the parameters of that callback and the data structure used to return the retrieved context.

10.4.1 LoadDocumentCallback

The LoadDocumentCallback defines a callback that custom document loaders have to implement to be used to retrieve remote documents and contexts. The callback returns a Promise resolving to a RemoteDocument. On failure, the Promise is rejected with an appropriate error code.

callback LoadDocumentCallback = Promise<RemoteDocument> (
  USVString url,
  optional LoadDocumentOptions? options
);
url
The URL of the remote document or context to load.
options
A set of options to determine the behavior of the callback. See .

The following algorithm describes the default callback and places requirements on implementations of the callback.

  1. Create a new Promise promise and return it. The following steps are then executed asynchronously.
  2. Set document to the body retrieved from the resource identified by url, or by otherwise locating a resource associated with url. When requesting remote documents the request MUST prefer Content-Type application/ld+json followed by application/json.

    If requestProfile is set, it MUST be added as a profile on application/ld+json.

    Processors MAY include other media types using a +json suffix as defined in [RFC6839].

    A full Processor MUST include text/html at any preference level.

  3. Set documentUrl to the location of the retrieved resource considering redirections (exclusive of HTTP status 303 "See Other" redirects as discussed in [cooluris]).
  4. If the retrieved resource's Content-Type is application/json or any media type with a +json suffix as defined in [RFC6839] except application/ld+json, and the response has an HTTP Link Header [RFC8259] using the http://www.w3.org/ns/json-ld#context link relation, set contextUrl to the associated href.

    If multiple HTTP Link Headers using the http://www.w3.org/ns/json-ld#context link relation are found, the promise is rejected with a JsonLdError whose code is set to multiple context link headers and processing is terminated.

    Processors MAY transform document to the internal representation.

    Note

    The HTTP Link Header is ignored for documents served as application/ld+json or text/html.

  5. Otherwise, if the retrieved resource's Content-Type is text/html:
    1. If the processor is a pure JSON Processor the promise is rejected with a JsonLdError whose code is set to loading document failed and processing is terminated.
    2. Set documentUrl to the the Document Base URL of url, as defined in [HTML], using the existing documentUrl as the document's URL.
      (Feature at Risk) Issue
      The use of the Document Base URL from [HTML] for setting the base IRI of the enclosed JSON-LD is an experimental feature, which may be changed in a future version of this specification.
    3. If the url parameter contains a fragment identifier, set source to the textContent of the script element in document having an id attribute that matches the fragment identifier, after decoding percent encoded sequences.

      If no such element is found, or the located element is not a JSON-LD script element, the promise is rejected with a JsonLdError whose code is set to loading document failed and processing is terminated.

    4. Otherwise, if the profile option is specified, set source to the result of transforming the textContent of the first script element in document having an type attribute of application/ld+json along with the value of the profile option, if found.
    5. If source is still undefined and the extractAllScripts option is not present, or false, set source to the textContent of the first JSON-LD script element in document.

      If no such element is found, or the located element is not a JSON-LD script element, the promise is rejected with a JsonLdError whose code is set to loading document failed and processing is terminated.

    6. If source is defined, set document to the result of the Extract Script Content algorithm, using source, rejecting promise with a JsonLdError whose code set from the result, if an error is detected and processing is terminated.
    7. Otherwise, source is undefined.
      1. If the extractAllScripts option is not present, or false, the promise is rejected with a JsonLdError whose code is set to loading document failed and processing is terminated.
      2. Otherwise, the extractAllScripts option is true. Set document to a new empty array. For each JSON-LD script element in input:
        1. Set source to its textContent.
        2. Set script content to the result of the Extract Script Content algorithm, using source, rejecting promise with a JsonLdError whose code set from the result, if an error is detected and processing is terminated.
        3. If script content is an array, merge it to the end of document.
        4. Otherwise, append script content to document.
  6. Otherwise, the retrieved document's Content-Type is neither application/json, application/ld+json, text/html, nor any other media type using a +json suffix as defined in [RFC6839]. Reject the promise passing a loading document failed error.
  7. Create a new RemoteDocument remote document using document, the returned Content-Type (without parameters) as contentType, any returned profile parameter, and any contextUrl.
  8. Resolve the promise with remote document.
Note

A custom LoadDocumentCallback set via the documentLoader option might be used to maintain a local cache of well-known context documents or to implement application-specific URL protocols.

10.4.2 LoadDocumentOptions

The LoadDocumentOptions type is used to pass various options to the LoadDocumentCallback.

dictionary LoadDocumentOptions {
  boolean  extractAllScripts = false;
  USVString profile = null;
  (USVString or sequence<USVString>) requestProfile = null;
};
extractAllScripts
If set to true, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary.
profile
When the resulting contentType is text/html, this option determines the profile to use for selecting a JSON-LD script elements.
requestProfile
One or more IRIs to use in the request as a profile parameter. (See IANA Considerations in [JSON-LD11]).

10.4.3 RemoteDocument

The RemoteDocument type is used by a LoadDocumentCallback to return information about a remote document or context.

dictionary RemoteDocument {
  USVString contextUrl = null;
  USVString documentUrl;
  any       document;
  USVString contentType;
  USVString profile = null;
};
contextUrl
If available, the value of the HTTP Link Header [RFC8259] using the http://www.w3.org/ns/json-ld#context link relation in the response. If the response's Content-Type is application/ld+json, the HTTP Link Header is ignored. If multiple HTTP Link Headers using the http://www.w3.org/ns/json-ld#context link relation are found, the Promise of the LoadDocumentCallback is rejected with a JsonLdError whose code is set to multiple context link headers.
documentUrl
The final URL of the loaded document. This is important to handle HTTP redirects properly.
document
The retrieved document. This can either be the raw payload or the already parsed document.
contentType
The Content-Type of the loaded document, exclusive of any optional parameters.
profile
The value of any profile parameter retrieved as part of the original contentType.

10.5 Error Handling

This section describes the datatype definitions used within the JSON-LD API for error handling.

10.5.1 JsonLdError

The JsonLdError type is used to report processing errors.

dictionary JsonLdError {
  JsonLdErrorCode code;
  USVString?      message = null;
};
code
A string representing the particular error type, as described in the various algorithms in this document.
message
An optional error message containing additional debugging information. The specific contents of error messages are outside the scope of this specification.

10.5.2 JsonLdErrorCode

The JsonLdErrorCode represents the collection of valid JSON-LD error codes.

enum JsonLdErrorCode {
    "colliding keywords",
    "conflicting indexes",
    "cyclic IRI mapping",
    "invalid @id value",
    "invalid @index value",
    "invalid @nest value",
    "invalid @prefix value",
    "invalid @propagate value",
    "invalid @reverse value",
    "invalid @import value",
    "invalid @version value",
    "invalid base IRI",
    "invalid container mapping",
    "invalid context entry",
    "invalid context nullification",
    "invalid default language",
    "invalid @included value",
    "invalid IRI mapping",
    "invalid keyword alias",
    "invalid language map value",
    "invalid language mapping",
    "invalid language-tagged string",
    "invalid language-tagged value",
    "invalid local context",
    "invalid remote context",
    "invalid reverse property",
    "invalid reverse property map",
    "invalid reverse property value",
    "invalid scoped context",
    "invalid script element",
    "invalid set or list object",
    "invalid term definition",
    "invalid type mapping",
    "invalid type value",
    "invalid typed value",
    "invalid value object",
    "invalid value object value",
    "invalid vocab mapping",
    "IRI confused with prefix",
    "keyword redefinition",
    "loading document failed",
    "loading remote context failed",
    "multiple context link headers",
    "processing mode conflict",
    "protected term redefinition",
    "context overflow"
};
colliding keywords
Two properties which expand to the same keyword have been detected. This might occur if a keyword and an alias thereof are used at the same time.
conflicting indexes
Multiple conflicting indexes have been found for the same node.
context overflow
maximum number of @context URLs exceeded.
cyclic IRI mapping
A cycle in IRI mappings has been detected.
invalid @id value
An @id entry was encountered whose value was not a string.
invalid @import value
An invalid value for @import has been found.
invalid @included value
An included block contains an invalid value.
invalid @index value
An @index entry was encountered whose value was not a string.
invalid @nest value
An invalid value for @nest has been found.
invalid @prefix value
An invalid value for @prefix has been found.
invalid @propagate value
An invalid value for @propagate has been found.
invalid @reverse value
An invalid value for an @reverse entry has been detected, i.e., the value was not a map.
invalid @version value
The @version entry was used in a context with an out of range value.
invalid base IRI
An invalid base IRI has been detected, i.e., it is neither an absolute IRI nor null.
invalid container mapping
An @container entry was encountered whose value was not one of the following strings: @list, @set, or @index.
invalid context entry
An entry in a context is invalid due to processing mode incompatibility.
invalid context nullification
An attempt was made to nullify a context containing protected term definitions.
invalid default language
The value of the default language is not a string or null and thus invalid.
invalid IRI mapping
A local context contains a term that has an invalid or missing IRI mapping.
invalid keyword alias
An invalid keyword alias definition has been encountered.
invalid language map value
An invalid value in a language map has been detected. It MUST be a string or an array of strings.
invalid language mapping
An @language entry in a term definition was encountered whose value was neither a string nor null and thus invalid.
invalid language-tagged string
A language-tagged string with an invalid language value was detected.
invalid language-tagged value
A number, true, or false with an associated language tag was detected.
invalid local context
In invalid local context was detected.
invalid remote context
No valid context document has been found for a referenced remote context.
invalid reverse property
An invalid reverse property definition has been detected.
invalid reverse property map
An invalid reverse property map has been detected. No keywords apart from @context are allowed in reverse property maps.
invalid reverse property value
An invalid value for a reverse property has been detected. The value of an inverse property must be a node object.
invalid scoped context
The local context defined within a term definition is invalid.
invalid script element
A script element in HTML input which is the target of a fragment identifier does not have an appropriate type attribute.
invalid set or list object
A set object or list object with disallowed entries has been detected.
invalid term definition
An invalid term definition has been detected.
invalid type mapping
An @type entry in a term definition was encountered whose value could not be expanded to an absolute IRI.
invalid type value
An invalid value for an @type entry has been detected, i.e., the value was neither a string nor an array of strings.
invalid typed value
A typed value with an invalid type was detected.
invalid value object
A value object with disallowed entries has been detected.
invalid value object value
An invalid value for the @value entry of a value object has been detected, i.e., it is neither a scalar nor null.
invalid vocab mapping
An invalid vocabulary mapping has been detected, i.e., it is neither an IRI nor null.
IRI confused with prefix
When compacting an absolute IRI would result in an absolute IRI which could be confused with a compact IRI (because its IRI scheme matches a term definition and it has no IRI authority).
keyword redefinition
A keyword redefinition has been detected.
loading document failed
The document could not be loaded or parsed as JSON.
loading remote context failed
There was a problem encountered loading a remote context.
multiple context link headers
Multiple HTTP Link Headers [RFC8259] using the http://www.w3.org/ns/json-ld#context link relation have been detected.
processing mode conflict
An attempt was made to change the processing mode which is incompatible with the previous specified version.
protected term redefinition
An attempt was made to redefine a protected term.

11. Security Considerations

See, Security Considerations in [JSON-LD11].

12. Privacy Considerations

See, Privacy Considerations in [JSON-LD11].

13. Internationalization Considerations

See, Internationalization Considerations in [JSON-LD11].

A. IDL Index

This section is non-normative.

[Exposed=Window]
interface JsonLdProcessor {
  static Promise<JsonLdDictionary> compact(
    JsonLdInput input,
    optional JsonLdContext context = {},
    optional JsonLdOptions options = {});
  static Promise<sequence<JsonLdDictionary>> expand(
    JsonLdInput input,
    optional JsonLdOptions options = {});
  static Promise<JsonLdDictionary> flatten(
    JsonLdInput input,
    optional JsonLdContext context = {},
    optional JsonLdOptions options = {});
  static Promise<sequence<JsonLdDictionary>> fromRdf(
    RdfDataset input,
    optional JsonLdOptions options = {});
  static Promise<RdfDataset> toRdf(
    JsonLdInput input,
    optional JsonLdOptions options = {});
};

dictionary JsonLdDictionary {};

typedef (JsonLdDictionary or sequence<JsonLdDictionary> or USVString) JsonLdInput;

typedef (JsonLdDictionary or USVString or sequence<(JsonLdDictionary or USVString)>) JsonLdContext;

[Constructor, Exposed=Window]
interface RdfDataset {
  readonly attribute RdfGraph defaultGraph;
  void add(USVString graphName, RdfGraph graph);
  iterable<USVString?, RdfGraph>;
};

[Constructor, Exposed=Window]
interface RdfGraph {
  void add(RdfTriple triple);
  iterable<RdfTriple>;
};

[Constructor, Exposed=Window]
interface RdfTriple {
  readonly attribute USVString subject;
  readonly attribute USVString predicate;
  readonly attribute (USVString or RdfLiteral) object;
};

[Constructor, Exposed=Window]
interface RdfLiteral {
  readonly attribute USVString value;
  readonly attribute USVString datatype;
  readonly attribute USVString? language;
};

dictionary JsonLdOptions {
  USVString?             base;
  boolean                compactArrays = true;
  boolean                compactToRelative = true;
  LoadDocumentCallback   documentLoader = null;
  (JsonLdDictionary? or USVString) expandContext = null;
  boolean                extractAllScripts = false;
  boolean                frameExpansion = false;
  boolean                ordered = false;
  USVString              processingMode = null;
  boolean                produceGeneralizedRdf = true;
  boolean                useNativeTypes = false;
  boolean                useRdfType = false;
};

callback LoadDocumentCallback = Promise<RemoteDocument> (
  USVString url,
  optional LoadDocumentOptions? options
);

dictionary LoadDocumentOptions {
  boolean  extractAllScripts = false;
  USVString profile = null;
  (USVString or sequence<USVString>) requestProfile = null;
};

dictionary RemoteDocument {
  USVString contextUrl = null;
  USVString documentUrl;
  any       document;
  USVString contentType;
  USVString profile = null;
};

dictionary JsonLdError {
  JsonLdErrorCode code;
  USVString?      message = null;
};

enum JsonLdErrorCode {
    "colliding keywords",
    "conflicting indexes",
    "cyclic IRI mapping",
    "invalid @id value",
    "invalid @index value",
    "invalid @nest value",
    "invalid @prefix value",
    "invalid @propagate value",
    "invalid @reverse value",
    "invalid @import value",
    "invalid @version value",
    "invalid base IRI",
    "invalid container mapping",
    "invalid context entry",
    "invalid context nullification",
    "invalid default language",
    "invalid @included value",
    "invalid IRI mapping",
    "invalid keyword alias",
    "invalid language map value",
    "invalid language mapping",
    "invalid language-tagged string",
    "invalid language-tagged value",
    "invalid local context",
    "invalid remote context",
    "invalid reverse property",
    "invalid reverse property map",
    "invalid reverse property value",
    "invalid scoped context",
    "invalid script element",
    "invalid set or list object",
    "invalid term definition",
    "invalid type mapping",
    "invalid type value",
    "invalid typed value",
    "invalid value object",
    "invalid value object value",
    "invalid vocab mapping",
    "IRI confused with prefix",
    "keyword redefinition",
    "loading document failed",
    "loading remote context failed",
    "multiple context link headers",
    "processing mode conflict",
    "protected term redefinition",
    "context overflow"
};

B. Open Issues

This section is non-normative.

The following is a list of issues open at the time of publication.

Issue 76: More compact @prefix defer-future-version

More compact @prefix.

Issue 94: Expansion concept "key's term definition" is unclear with compact IRI keys defer-future-version

Expansion concept "key's term definition" is unclear with compact IRI keys.

C. Changes since 1.0 Recommendation of 16 January 2014

This section is non-normative.

Additionally, see § D. Changes since JSON-LD Community Group Final Report.

D. Changes since JSON-LD Community Group Final Report

This section is non-normative.

E. Acknowledgements

This section is non-normative.

The editor would like to specially thank the following individuals for making significant contributions to the authoring and editing of this specification:

Additionally, the following people were members of the Working Group at the time of publication:

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: Chris Webber, David Wood, Drummond Reed, Eleanor Joslin, Fabien Gandon, Herm Fisher, Jamie Pitts, Kim Hamilton Duffy, Niklas Lindström, Paolo Ciccarese, Paul Frazze, Paul Warren, Reto Gmür, Rob Trainer, Ted Thibodeau Jr., and Victor Charpenay.

F. References

F.1 Normative references

[BCP47]
Tags for Identifying Languages. A. Phillips; M. Davis. IETF. September 2009. IETF Best Current Practice. URL: https://tools.ietf.org/html/bcp47
[DOM]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.github.io/ecma262/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[IEEE-754-2008]
IEEE 754-2008 Standard for Floating-Point Arithmetic. Institute of Electrical and Electronics Engineers. 2008. URL: http://standards.ieee.org/findstds/standard/754-2008.html
[INFRA]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[JSON-LD]
JSON-LD 1.0. Manu Sporny; Gregg Kellogg; Markus Lanthaler. W3C. 16 January 2014. W3C Recommendation. URL: https://www.w3.org/TR/json-ld/
[JSON-LD11]
JSON-LD 1.1. Gregg Kellogg; Pierre-Antoine Champin. W3C. 10 May 2019. W3C First Public Working Draft. URL: https://w3c.github.io/json-ld-syntax/
[JSON-LD11-API]
JSON-LD 1.1 Processing Algorithms and API. Gregg Kellogg. W3C. 10 May 2019. W3C First Public Working Draft. URL: https://w3c.github.io/json-ld-api/
[JSON-LD11-FRAMING]
JSON-LD 1.1 Framing. Gregg Kellogg. W3C. 10 May 2019. W3C First Public Working Draft. URL: https://w3c.github.io/json-ld-framing/
[LINKED-DATA]
Linked Data Design Issues. Tim Berners-Lee. W3C. 27 July 2006. W3C-Internal Document. URL: https://www.w3.org/DesignIssues/LinkedData.html
[promises-guide]
Writing Promise-Using Specifications. Domenic Denicola. W3C. 9 November 2018. TAG Finding. URL: https://www.w3.org/2001/tag/doc/promises-guide
[RDF-SCHEMA]
RDF Schema 1.1. Dan Brickley; Ramanathan Guha. W3C. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/rdf-schema/
[RDF11-CONCEPTS]
RDF 1.1 Concepts and Abstract Syntax. Richard Cyganiak; David Wood; Markus Lanthaler. W3C. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/rdf11-concepts/
[RDF11-MT]
RDF 1.1 Semantics. Patrick Hayes; Peter Patel-Schneider. W3C. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/rdf11-mt/
[RFC2045]
Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies. N. Freed; N. Borenstein. IETF. November 1996. Draft Standard. URL: https://tools.ietf.org/html/rfc2045
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986
[RFC3987]
Internationalized Resource Identifiers (IRIs). M. Duerst; M. Suignard. IETF. January 2005. Proposed Standard. URL: https://tools.ietf.org/html/rfc3987
[RFC6839]
Additional Media Type Structured Syntax Suffixes. T. Hansen; A. Melnikov. IETF. January 2013. Informational. URL: https://tools.ietf.org/html/rfc6839
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://tools.ietf.org/html/rfc8174
[RFC8259]
The JavaScript Object Notation (JSON) Data Interchange Format. T. Bray, Ed.. IETF. December 2017. Internet Standard. URL: https://tools.ietf.org/html/rfc8259
[Turtle]
RDF 1.1 Turtle. Eric Prud'hommeaux; Gavin Carothers. W3C. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/turtle/
[WEBIDL]
Web IDL. Boris Zbarsky. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
[XMLSCHEMA11-2]
W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes. David Peterson; Sandy Gao; Ashok Malhotra; Michael Sperberg-McQueen; Henry Thompson; Paul V. Biron et al. W3C. 5 April 2012. W3C Recommendation. URL: https://www.w3.org/TR/xmlschema11-2/

F.2 Informative references

[cooluris]
Cool URIs for the Semantic Web. Leo Sauermann; Richard Cyganiak. W3C. 3 December 2008. W3C Note. URL: https://www.w3.org/TR/cooluris/
[JCS]
JSON Canonicalization Scheme (JCS). A. Rundgren; B. Jordan; S. Erdtman. Network Working Group. February 16, 2019. Internet-Draft. URL: https://tools.ietf.org/html/draft-rundgren-json-canonicalization-scheme-05
[JSON-LD-TESTS]
JSON-LD 1.0 Test Suite. RDF Working Group. W3C. 11 April 2013. W3C Editor's Draft. URL: https://www.w3.org/2013/json-ld-tests/