This specification defines an Application Programming Interface (API)
and a set of algorithms for programmatic transformations of JSON-LD
documents. Restructuring data according to the defined transformations
often dramatically simplifies its usage.
This document has been under development for over 25 months in the
JSON for Linking Data Community Group. The document has recently been
transferred to the RDF Working Group for review, improvement, and publication
along the Recommendation track. The specification has undergone significant
development, review, and changes during the course of the last 25 months.
There are several independent
interoperable implementations of
this specification. There is a fairly complete test suite [[JSON-LD-TESTS]]
and a live JSON-LD editor
that is capable of demonstrating the features described in
this document. While there will be continuous development on implementations,
the test suite, and the live editor, they are believed to be mature enough
to be integrated into a non-production system at this point in time. There
is an expectation that they could be used in a production system within the
next six months.
There are a number of ways that one may participate in the development of
this specification:
- If you want to make sure that your feedback is formally addressed by
the RDF Working Group, you should send it to public-rdf-comments:
public-rdf-comments@w3.org
- Ad-hoc technical discussion primarily occurs on the public community mailing list:
public-linked-json@w3.org
- Public JSON-LD Community Group teleconferences
are held on Tuesdays at 1500UTC every week. Participation is open to the
public.
- RDF Working Group teleconferences are held on Wednesdays at 1500UTC
every week. Participation is limited to RDF Working Group members.
- Specification bugs and issues should be reported in the
issue tracker
if you do not want to send an email to the public-rdf-comments mailing
list.
- Source code
for the specification can be found on Github.
- The #json-ld
IRC channel is available for real-time discussion on irc.freenode.net.
Changes since the
11 April 2013 Last Call Working Draft:
- Use of DOM Futures instead of callbacks in the Application Programming Interface
- Processing of terms that are redefined to themselves without raising an
cyclic IRI mapping
error
- Raise an
invalid IRI mapping
error if relative URLs are used in term definitions
- Support relative IRIs in
@base
- Remove default value of
JsonLdOption's
base
member
- Support lists of lists when serializing from RDF to JSON-LD
- Support for relative URLs in
@base
and documents that
do not have a base value
Changes since the
16 May 2013 Last Call Working Draft:
- Ensure determinism of the Deserialize to RDF Algorithm by specifying the processing order
- Change the default value of the use native types flag in the Serialize from RDF Algorithm
to
false
- Clarify that the identifier map and the counter used by the
Generate Blank Node Identifier algorithm are reset before running the Flattening
and the Deserialize to RDF algorithms
- Raise an error if a blank node is used as data type
- Clarify that blank node identifier are supported as value of
@vocab
- When generating RDF, exclude triples containing a
blank node predicate, unless the
produce extended RDF flag is set
- Update reference to DOM Promises (have been called DOM Futures)
- Fix bug in Serialize from RDF algorithm to
handle lists correctly
- Support processing of documents with a
+json
media type as defined in
[[RFC6839]]
- Use the LoadDocumentCallback (previously
LoadContextCallback
)
to retrieve remote contexts and remote documents
Features
The JSON-LD Syntax specification [[!JSON-LD]] 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.
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.
There are four major types of transformation that are discussed in this
document: expansion, compaction, flattening, and RDF serialization/deserialization.
Conformance
All examples and notes as well as sections marked as non-normative in this
specification are non-normative. Everything else in this specification is
normative.
The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
MAY, and OPTIONAL in this specification are to be interpreted as described
in [[!RFC2119]].
There are three classes of products that can claim conformance to this
specification: JSON-LD Processors,
JSON-LD API Implementations,
and JSON-LD-RDF Serializers/Deserializers.
A conforming JSON-LD Processor is a system which can perform the
Expansion, Compaction,
and Flattening operations defined in this specification.
A conforming JSON-LD API Implementation is a conforming JSON-LD Processor
that exposes the Application Programming Interface (API)
defined in this specification. It MUST implement the json-ld-1.0
processing mode (for further details, see the
processingMode
option of JsonLdOptions).
JSON-LD Processors and
API Implementations 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 JSON-LD-RDF Serializer/Deserializer is a system that can perform
Deserialization to RDF and
Serialization from RDF.
The algorithms in this specification are generally written with more concern for clarity
than efficiency. Thus, JSON-LD Processors
and API Implementations 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.
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.
General Terminology
This document uses the following terms as defined in JSON [[!RFC4627]]. Refer
to the JSON Grammar section in [[!RFC4627]] for formal definitions.
- JSON object
- An object structure is represented as a pair of curly brackets surrounding
zero or more key-value pairs. A key is a string.
A single colon comes after each key, separating the key from the value.
A single comma separates a value from a following key. In contrast to JSON,
in JSON-LD the keys in an object must be unique.
- array
- An array structure is represented as square brackets surrounding zero
or more values. Values are separated by commas.
In JSON, an array is an ordered sequence 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 specification [[JSON-LD]]).
- string
- A string is a sequence of zero or more Unicode characters,
wrapped in double quotes, using backslash escapes (if necessary). A
character is represented as a single character string.
- number
- 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.
- true and false
- Values that are used to express one of two possible boolean states.
- null
- The null value. A key-value pair in the
@context
where the value, or the @id
of the
value, is null explicitly decouples a term's association
with an IRI. A key-value pair in the body of a JSON-LD document whose
value is null has the same meaning as if the key-value pair
was not defined. If @value
, @list
, or
@set
is set to null in expanded form, then
the entire JSON object is ignored.
Furthermore, the following terminology is used throughout this document:
- keyword
- A JSON key that is specific to JSON-LD, specified in the section
Syntax Tokens and Keywords
of the JSON-LD specification [[!JSON-LD]].
- context
- A set of rules for interpreting a JSON-LD document as specified in the section
The Context of the JSON-LD
specification [[!JSON-LD]].
- 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.
- named graph
- A named graph is a pair consisting of an IRI or blank node
(the graph name) and a graph.
- default graph
- The default graph is the only graph in a JSON-LD document which has no graph name.
- Graph
- A labeled directed graph, i.e., a set of nodes
connected by edges,
as specified in the Data Model
section of the JSON-LD specification [[!JSON-LD]].
- edge
- Every edge has a direction associated with it and is labeled with
an IRI or a blank node identifier. Within the JSON-LD syntax
these edge labels are called properties. Whenever possible, an
edge should be labeled with an IRI.
- node
- Every node is an IRI, a blank node,
a JSON-LD value, or a list.
- IRI
- An IRI (Internationalized Resource Identifier) is a string that conforms to the syntax
defined in [[RFC3987]].
- absolute IRI
- An absolute IRI is defined in [[!RFC3987]] containing a scheme along with a path and
optional query and fragment segments.
- relative IRI
- A relative IRI is an IRI that is relative to some other absolute IRI.
- blank node
- A node in a graph that is neither an
IRI, nor a JSON-LD value, nor a list.
- 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
_:
.
- JSON-LD value
- A JSON-LD value is a string, a number,
true or false, a typed value, or a
language-tagged string.
- typed value
- A typed value consists of a value, which is a string, and a type,
which is an IRI.
- 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.
- list
- A list is an ordered sequence of IRIs,
blank nodes, and
JSON-LD values.
Algorithm Terms
- active graph
- The name of the currently active graph that the processor should use when
processing.
- active subject
- The currently active subject that the processor should use when
processing.
- active property
- The currently active property or keyword that
the processor should use when processing.
- active context
- A context that is used to resolve terms while
the processing algorithm is running.
- local context
- A context that is specified within a JSON object,
specified via the
@context
keyword.
- JSON-LD input
- The JSON-LD data structure that is provided as input to the algorithm.
- term
- A term is a short word defined in a context that may be expanded to
an IRI
- 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.
- node object
- A node object represents zero or more properties of a
node in the graph serialized by the
JSON-LD document. A JSON object 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 JSON object in the JSON-LD document consisting
of no other members than
@graph
and @context
.
- value object
- A value object is a JSON object that has an
@value
member.
- list object
- A list object is a JSON object that has an
@list
member.
- set object
- A set object is a JSON object that has an
@set
member.
- scalar
- A scalar is either a JSON string, number, true,
or false.
- RDF subject
- A subject
as specified by [[RDF11-CONCEPTS]].
- RDF predicate
- A predicate
as specified by [[RDF11-CONCEPTS]].
- RDF object
- An object
as specified by [[RDF11-CONCEPTS]].
- RDF triple
- A triple
as specified by [[RDF11-CONCEPTS]].
- RDF dataset
- A dataset
as specified by [[RDF11-CONCEPTS]] representing a collection of
RDF graphs.
Context Processing Algorithms
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
properties and values have to be interpreted as well as the current base IRI,
the vocabulary mapping and the default language. Each
term definition consists of an IRI mapping, a boolean
flag reverse property, an optional type mapping
or language mapping, and an optional container mapping.
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, the 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.
Algorithm
This algorithm specifies how a new active context is updated
with a local context. The algorithm takes three input variables:
an active context, a local context, and an array
remote contexts which is used to detect cyclical context inclusions.
If remote contexts is not passed, it is initialized to an empty
array.
- Initialize result to the result of cloning
active context.
- If local context is not an array,
set it to an array containing only
local context.
-
For each item context in local context:
- If context is null, set result to a
newly-initialized active context and continue with the
next context. The base IRI of the
active context is set to the IRI of the currently being processed
document (which might be different from the currently being processed context),
if available; otherwise to null. If set, the
compactArrays
option of a JSON-LD API Implementation overrides the base IRI.
- If context is a string,
- 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]].
- If context is in the remote contexts array, a
recursive context inclusion
error has been detected and processing is aborted;
otherwise, add context to remote contexts.
- Dereference context. If context cannot be dereferenced, a
loading remote context failed
error has been detected and processing is aborted. If the dereferenced document has no
top-level JSON object with an @context
member, an
invalid remote context
has been detected and processing is aborted; otherwise,
set context to the value of that member.
- Set result to the result of recursively calling this algorithm,
passing result for active context,
context for local context, and remote contexts.
- Continue with the next context.
- If context is not a JSON object, an
invalid local context
error has been detected and processing is aborted.
- If context has an
@base
key and remote contexts is empty, i.e., the currently
being processed context is not a remote context:
- Initialize value to the value associated with the
@base
key.
- If value is null, remove the
base IRI of result.
- Otherwise, if value is an absolute IRI,
the base IRI of result is set to value.
- 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.
- Otherwise, an
invalid base IRI
error has been detected and processing is aborted.
- If context has an
@vocab
key:
- Initialize value to the value associated with the
@vocab
key.
- If value is null, remove
any vocabulary mapping from result.
- Otherwise, if value is an absolute IRI
or blank node identifier, the vocabulary mapping
of result is set to value. If it is not an
absolute IRI or blank node identifier, an
invalid vocab mapping
error has been detected and processing is aborted.
- If context has an
@language
key:
- Initialize value to the value associated with the
@language
key.
- If value is null, remove
any default language from result.
- 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.
- Create a JSON object defined to use to keep
track of whether or not a term has already been defined
or currently being defined during recursion.
- For each key-value pair in context where
key is not
@base
, @vocab
, or
@language
, invoke the
Create Term Definition algorithm,
passing result for active context,
context for local context, key,
and defined.
- Return result.
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.
Algorithm
The algorithm has four required inputs which are:
an active context, a local context,
a term, and a map defined.
- If defined contains the key 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.
- Set the value associated with defined's term key to
false. This indicates that the term definition
is now being created but is not yet complete.
- Since keywords cannot be overridden,
term must not be a keyword. Otherwise, a
keyword redefinition
error has been detected and processing is aborted.
- Remove any existing term definition for term in
active context.
- Initialize value to a copy of the value associated with the key
term in local context.
- If value is null or value
is a JSON object containing the key-value pair
@id
-null, set the
term definition in active context to
null, set the value associated with defined's
key term to true, and return.
- Otherwise, if value is a string, convert it
to a JSON object consisting of a single member whose
key is
@id
and whose value is value.
- Otherwise, value must be a JSON object, if not, an
invalid term definition
error has been detected and processing is aborted.
- Create a new term definition, definition.
- If value contains the key
@type
:
- Initialize type to the value associated with the
@type
key, which must be a string. Otherwise, an
invalid type mapping
error has been detected and processing is aborted.
- Set type to the result of using the
IRI Expansion algorithm, passing
active context, type for value,
true for vocab,
false for document relative,
local context, and defined. If the expanded type is
neither
@id
, nor @vocab
, nor an absolute IRI, an
invalid type mapping
error has been detected and processing is aborted.
- Set the type mapping for definition to type.
- If value contains the key
@reverse
:
- If value contains an
@id
, member, an
invalid reverse property
error has been detected and processing is aborted.
- If the value associated with the
@reverse
key
is not a string, an
invalid IRI mapping
error has been detected and processing is aborted.
- 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
key for value, true
for vocab, false for document relative,
local context, and defined. If the result
is not an absolute IRI, i.e., it contains no
colon (:
), an
invalid IRI mapping
error has been detected and processing is aborted.
- If value contains an
@container
member,
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.
- Set the reverse property flag of definition
to true.
- Set the term definition of term in
active context to definition and the
value associated with defined's key term to
true and return.
- Set the reverse property flag of definition
to false.
- If value contains the key
@id
and its value
does not equal term:
- If the value associated with the
@id
key is not a string, an
invalid IRI mapping
error has been detected and processing is aborted.
- 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
key for
value, true for vocab,
false for document relative,
local context, and defined. If the resulting
IRI mapping equals @context
, an
invalid keyword alias
error has been detected and processing is aborted.
-
Otherwise if the term contains a colon (
:
):
- If term is a compact IRI with a
prefix that is a key in local context
a dependency has been found. Use this algorithm recursively passing
active context, local context, the
prefix as term, and defined.
- 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.
- Otherwise, term is an absolute IRI. Set the
IRI mapping of definition to term.
- 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.
- If value contains the key
@container
:
- Initialize container to the value associated with the
@container
key, which must be either
@list
, @set
, @index
,
or @language
. Otherwise, an
invalid container mapping
error
has been detected and processing is aborted.
- Set the container mapping of definition to
container.
- If value contains the key
@language
and
does not contain the key @type
:
- Initialize language to the value associated with the
@language
key, which must be either null
or a string. Otherwise, an
invalid language mapping
error has been detected and processing is aborted.
- If language is a string set it to
lowercased language. Set the language mapping
of definition to language.
- Set the term definition of term in
active context to definition and set the value
associated with defined's key term to
true.
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.
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.
- If value is a keyword or null,
return value as is.
- If local context is not null, it contains
a key that equals value, and the value associated with the key
that equals 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.
- If vocab is true and the
active context has a term definition for
value, return the associated IRI mapping.
- If value contains a colon (
:
), it is either
an absolute IRI or a compact IRI:
- Split value into a prefix and suffix
at the first occurrence of a colon (
:
).
- 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.
- If local context is not null, it
contains a key that equals prefix, and the value
associated with the key that equals prefix 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.
- If active context contains a term definition
for prefix, return the result of concatenating
the IRI mapping associated with prefix and
suffix.
- Return value as it is already an absolute IRI.
- If vocab is true, and
active context has a vocabulary mapping,
return the result of concatenating the vocabulary mapping
with value.
- 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]].
- If local context is not null and
value is not an absolute IRI, an
invalid IRI mapping
error has been detected and processing is aborted.
- Otherwise, return value as is.
Expansion Algorithms
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.
Algorithm
The algorithm takes three input variables: an active context,
an active property, and an element to be expanded.
To begin, the active context is set to the result of performing,
Context Processing on the passed
expandContext
,
or empty if expandContext
is null, active property is set to null,
and element is set to the JSON-LD input.
- If element is null, return null.
- If element is a scalar,
- If active property is null or
@graph
,
drop the free-floating scalar by returning null.
- Return the result of the
Value Expansion algorithm, passing the
active context, active property, and
element as value.
- If element is an array,
- Initialize an empty array, result.
- For each item in element:
- Initialize expanded item to the result of using this
algorithm recursively, passing active context,
active property, and item as element.
- If the active property is
@list
or its
container mapping is set to @list
, the
expanded item must not be an array or a
list object, otherwise a
list of lists
error has been detected and processing is aborted.
- If expanded item is an array, append each
of its items to result. Otherwise, if
expanded item is not null, append it to result.
- Return result.
- Otherwise element is a JSON object.
- If element contains the key
@context
, set
active context to the result of the
Context Processing algorithm,
passing active context and the value of the
@context
key as local context.
- Initialize an empty JSON object, result.
- For each key and value in element,
ordered lexicographically by key:
- If key is
@context
, continue to
the next key.
- Set expanded property to the result of
using the IRI Expansion algorithm,
passing active context, key for
value, and true for vocab.
- If expanded property is null or it neither
contains a colon (
:
) nor it is a keyword,
drop key by continuing to the next key.
- If expanded property is a keyword:
- If active property equals
@reverse
, an
invalid reverse property map
error has been detected and processing is aborted.
- If result has already an expanded property member, an
colliding keywords
error has been detected and processing is aborted.
- 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.
- 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
active context, true for vocab,
and true for document relative to expand the value
or each of its items.
- If expanded property is
@graph
, set
expanded value to the result of using this algorithm
recursively passing active context, @graph
for active property, and value for element.
- If expanded property is
@value
and
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
member 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
member depends
on the existence of an @value
member.
- 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.
- 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.
- If expanded property is
@list
:
- If active property is null or
@graph
, continue with the next key
from element to remove the free-floating list.
- Otherwise, initialize expanded value to the result of using
this algorithm recursively passing active context,
active property, and value for element.
- If expanded value is a list object, a
list of lists
error has been detected and processing is aborted.
- If expanded property is
@set
, set
expanded value to the result of using this algorithm
recursively, passing active context,
active property, and value for
element.
- If expanded property is
@reverse
and
value is not a JSON object, an
invalid @reverse value
error has been detected and processing is aborted. Otherwise
- Initialize expanded value to the result of using this
algorithm recursively, passing active context,
@reverse
as active property, and
value as element.
- If expanded value contains an
@reverse
member,
i.e., properties that are reversed twice, execute for each of its
property and item the following steps:
- If result does not have a property member, create
one and set its value to an empty array.
- Append item to the value of the property member
of result.
- If expanded value contains members other than
@reverse
:
- If result does not have an
@reverse
member, create
one and set its value to an empty JSON object.
- Reference the value of the
@reverse
member in result
using the variable reverse map.
- For each property and items in expanded value
other than
@reverse
:
- For each item in items:
- If item is a value object or list object, an
invalid reverse property value
has been detected and processing is aborted.
- If reverse map has no property member, create one
and initialize its value to an empty array.
- Append item to the value of the property
member in reverse map.
- Continue with the next key from element.
- Unless expanded value is null, set
the expanded property member of result to
expanded value.
- Continue with the next key from element.
- Otherwise, if key's container mapping in
active context is
@language
and
value is a JSON object then value
is expanded from a language map
as follows:
- Initialize expanded value to an empty
array.
- For each key-value pair language-language value
in value, ordered lexicographically by language:
- If language value is not an array
set it to an array containing only
language value.
- For each item in language value:
- item must be a string,
otherwise an
invalid language map value
error has been detected and processing is aborted.
- Append a JSON object to
expanded value that consists of two
key-value pairs: (
@value
-item)
and (@language
-lowercased
language).
- Otherwise, if key's container mapping in
active context is
@index
and
value is a JSON object then value
is expanded from an index map as follows:
- Initialize expanded value to an empty
array.
- For each key-value pair index-index value
in value, ordered lexicographically by index:
- If index value is not an array
set it to an array containing only
index value.
- Initialize index value to the result of
using this algorithm recursively, passing
active context,
key as active property,
and index value as element.
- For each item in index value:
- If item does not have the key
@index
, add the key-value pair
(@index
-index) to
item.
- Append item to expanded value.
- Otherwise, initialize expanded value to the result of
using this algorithm recursively, passing active context,
key for active property, and value
for element.
- If expanded value is null, ignore key
by continuing to the next key from element.
- If the container mapping associated to key in
active context is
@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 JSON object containing
the key-value pair @list
-expanded value.
- Otherwise, if the term definition associated to
key indicates that it is a reverse property
- If result has no
@reverse
member, create
one and initialize its value to an empty JSON object.
- Reference the value of the
@reverse
member in result
using the variable reverse map.
- If expanded value is not an array, set
it to an array containing expanded value.
- For each item in expanded value
- If item is a value object or list object, an
invalid reverse property value
has been detected and processing is aborted.
- If reverse map has no expanded property member,
create one and initialize its value to an empty array.
- Append item to the value of the expanded property
member of reverse map.
- Otherwise, if key is not a reverse property:
- If result does not have an expanded property
member, create one and initialize its value to an empty
array.
- Append expanded value to value of the expanded property
member of result.
- If result contains the key
@value
:
- The result must not contain any keys other than
@value
, @language
, @type
,
and @index
. It must not contain both the
@language
key and the @type
key.
Otherwise, an
invalid value object
error has been detected and processing is aborted.
- If the value of result's
@value
key is
null, then set result to null.
- Otherwise, if the value of result's
@value
member
is not a string and result contains the key
@language
, an
invalid language-tagged value
error has been detected (only strings
can be language-tagged) and processing is aborted.
- Otherwise, if the result has a
@type
member
and its value is not an IRI, an
invalid typed value
error has been detected and processing is aborted.
- Otherwise, if result contains the key
@type
and its associated value is not an array, set it to
an array containing only the associated value.
- Otherwise, if result contains the key
@set
or @list
:
- The result must contain at most one other key and that
key must be
@index
. Otherwise, an
invalid set or list object
error has been detected and processing is aborted.
- If result contains the key
@set
, then
set result to the key's associated value.
- If result contains only the key
@language
, set result to null.
- If active property is null or
@graph
,
drop free-floating values as follows:
- If result is an empty JSON object or contains
the keys
@value
or @list
, set result to
null.
- Otherwise, if result is a JSON object whose only
key is
@id
, set result to null.
- Return result.
If, after the above algorithm is run, the result is a
JSON object that contains only an @graph
key, 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.
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.
Algorithm
The algorithm takes three required inputs: an active context,
an active property, and a value to expand.
- If the active property has a type mapping
in active context that is
@id
, return a new
JSON object containing a single key-value pair 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.
- If active property has a type mapping in
active context that is
@vocab
, return
a new JSON object containing a single key-value pair
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.
- Otherwise, initialize result to a JSON object
with an
@value
member whose value is set to
value.
- If active property has a type mapping in
active context, add an
@type
member to
result and set its value to the value associated with the
type mapping.
- Otherwise, if value is a string:
- 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 member is added.
- Otherwise, if the active context has a
default language, add an
@language
to result and set its value to the
default language.
- Return result.
Compaction Algorithms
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.
Algorithm
The algorithm takes five required input variables: an active context,
an inverse context, an active property, an
element to be compacted, and a flag
compactArrays
.
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, and, if not passed,
compactArrays
is set to true.
- If element is a scalar, it is already in its most
compact form, so simply return element.
- If element is an array:
- Initialize result to an empty array.
- For each item in element:
- Initialize compacted item to the result of using this
algorithm recursively, passing active context,
inverse context, active property, and
item for element.
- If compacted item is not null, then append
it to result.
- If result contains only one item (it has a length of
1
), active property has no
container mapping in active context, and
compactArrays
is true, set result to its only item.
- Return result.
- Otherwise element is a JSON object.
- If element has an
@value
or @id
member and the result of using the
Value Compaction algorithm,
passing active context, inverse context,
active property,and element as value is
a scalar, return that result.
- Initialize inside reverse to true if
active property equals
@reverse
,
otherwise to false.
- Initialize result to an empty JSON object.
- For each key expanded property and value expanded value
in element, ordered lexicographically by expanded property:
- If expanded property is
@id
or
@type
:
- If expanded value is a string,
then initialize compacted value to the result
of using the IRI Compaction algorithm,
passing active context, inverse context,
expanded value for iri,
and true for vocab if
expanded property is
@type
,
false otherwise.
- Otherwise, expanded value must be a
@type
array:
- Initialize compacted value to an empty
array.
- For each item expanded type in
expanded value, append the result of
of using the IRI Compaction algorithm,
passing active context, inverse context,
expanded type for iri, and
true for vocab,
to compacted value.
- If compacted value contains only one
item (it has a length of
1
), then
set compacted value to its only item.
- Initialize alias to the result of using the
IRI Compaction algorithm,
passing active context, inverse context,
expanded property for iri,
and true for vocab.
- Add a member alias to result whose value is
set to compacted value and continue to the next
expanded property.
- If expanded property is
@reverse
:
- Initialize compacted value to the result of using this
algorithm recursively, passing active context,
inverse context,
@reverse
for
active property, and expanded value
for element.
- For each property and value in compacted value:
- If the term definition for property in the
active context indicates that property is
a reverse property
- If the term definition for property in
the active context has a
container mapping of
@set
or
compactArrays
is false, and value is not an
array, set value to a new
array containing only value.
- If property is not a member of
result, add one and set its value to value.
- Otherwise, if the value of the property member 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.
- Remove the property member from
compacted value.
- If compacted value has some remaining members, i.e.,
it is not an empty JSON object:
- Initialize alias to the result of using the
IRI Compaction algorithm,
passing active context, inverse context,
@reverse
for iri,
and true for vocab.
- Set the value of the alias member of result to
compacted value.
- Continue with the next expanded property from element.
- If expanded property is
@index
and
active property has a container mapping
in active context that is @index
,
then the compacted result will be inside of an @index
container, drop the @index
property by continuing
to the next expanded property.
- Otherwise, if expanded property is
@index
,
@value
, or @language
:
- Initialize alias to the result of using
the IRI Compaction algorithm,
passing active context, inverse context,
expanded property for iri,
and true for vocab.
- Add a member alias to result whose value is
set to expanded value and continue with the next
expanded property.
- If expanded value is an empty array:
- Initialize item active property to the result of
using the IRI Compaction algorithm,
passing active context, inverse context,
expanded property for iri,
expanded value for value,
true for vocab, and
inside reverse.
- If result does not have the key that equals
item active property, set this key's value in
result to an empty array. Otherwise, if
the key's value is not an array, then set it
to one containing only the value.
-
At this point, expanded value must be an
array due to the
Expansion algorithm.
For each item expanded item in expanded value:
- Initialize item active property to the result of using
the IRI Compaction algorithm,
passing active context, inverse context,
expanded property for iri,
expanded item for value,
true for vocab, and
inside reverse.
- Initialize container to null. If there
is a container mapping for
item active property in active context,
set container to its value.
- 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 key
@list
, otherwise pass
the key's associated value for element.
-
If expanded item is a list object:
- If compacted item is not an array,
then set it to an array containing only
compacted item.
- If container is not
@list
:
- Convert compacted item to a
list object by setting it to a
JSON object containing key-value pair
where the key is the result of the
IRI Compaction algorithm,
passing active context, inverse context,
@list
for iri, and compacted item
for value.
- If expanded item contains the key
@index
, then add a key-value pair
to compacted item where the key is the
result of the IRI Compaction algorithm,
passing active context, inverse context,
@index
as iri, and the value associated with the
@index
key in expanded item as value.
- Otherwise, item active property must not be a key
in result because there cannot be two
list objects associated
with an active property that has a
container mapping; a
compaction to list of lists
error has been detected and processing is aborted.
-
If container is
@language
or
@index
:
- If item active property is not a key in
result, initialize it to an empty JSON object.
Initialize map object to the value of item active property
in result.
- If container is
@language
and
compacted item contains the key
@value
, then set compacted item
to the value associated with its @value
key.
- Initialize map key to the value associated with
with the key that equals container in
expanded item.
- If map key is not a key in map object,
then set this key'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.
-
Otherwise,
- If
compactArrays
is false, container is @set
or
@list
, or expanded property is
@list
or @graph
and
compacted item is not an array,
set it to a new array
containing only compacted item.
- If item active property is not a key in
result then add the key-value pair,
(item active property-compacted item),
to result.
- Otherwise, if the value associated with the key that
equals item active property in 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.
- Return result.
If, after the algorithm outlined above is run, the result result
is an array, replace it with a new
JSON object with a single member whose key is the result
of using the IRI Compaction algorithm,
passing active context, inverse context, and
@graph
as iri and whose value is the array
result. Finally, if a non-empty context has been passed,
add an @context
member to result and set its value
to the passed context.
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 mappings,
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 mappings 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.
Algorithm
The algorithm takes one required input: the active context that
the inverse context is being created for.
- Initialize result to an empty JSON object.
- Initialize default language to
@none
. If the
active context has a default language,
set default language to it.
- 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):
- If the term definition is null,
term cannot be selected during compaction,
so continue to the next term.
- Initialize container to
@none
. If there
is a container mapping in
term definition, set container to
its associated value.
- Initialize iri to the value of the IRI mapping
for the term definition.
- If iri is not a key in result, add
a key-value pair where the key is iri and the value
is an empty JSON object to result.
- Reference the value associated with the iri member in
result using the variable container map.
- If container map has no container member,
create one and set its value to a new
JSON object with two members. The first member is
@language
and its value is a new empty
JSON object, the second member is @type
and its value is a new empty JSON object.
- Reference the value associated with the container member
in container map using the variable type/language map.
- If the term definition indicates that the term
represents a reverse property:
- Reference the value associated with the
@type
member in type/language map using the variable
type map.
- If type map does not have a
@reverse
member, create one and set its value to the term
being processed.
- Otherwise, if term definition has a
type mapping:
- Reference the value associated with the
@type
member in type/language map using the variable
type map.
- If type map does not have a member corresponding
to the type mapping in term definition,
create one and set its value to the term
being processed.
- Otherwise, if term definition has a
language mapping (might be null):
- Reference the value associated with the
@language
member in type/language map using the variable
language map.
- If the language mapping equals null,
set language to
@null
; otherwise set it
to the language code in language mapping.
- If language map does not have a language member,
create one and set its value to the term
being processed.
- Otherwise:
- Reference the value associated with the
@language
member in type/language map using the variable
language map.
- If language map does not have a default language
member, create one and set its value to the term
being processed.
- If language map does not have a
@none
member, create one and set its value to the term
being processed.
- Reference the value associated with the
@type
member in type/language map using the variable
type map.
- If type map does not have a
@none
member, create one and set its value to the term
being processed.
- Return result.
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.
Algorithm
This algorithm takes three required inputs and three optional inputs.
The required inputs are an active context, an inverse context,
and the iri to be compacted. The optional inputs are a value associated
with the iri, a vocab flag which specifies whether the
passed iri 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
.
- If iri is null, return null.
- If vocab is true and iri is a
key in inverse context:
- Initialize default language to
active context's
default language, if it has one, otherwise to
@none
.
- Initialize containers to an empty array. This
array will be used to keep track of an ordered list of
preferred container mappings
for a term, based on what is compatible with
value.
- 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.
- If value is a JSON object that contains the
key
@index
, then append the value @index
to containers.
- If reverse is true, set type/language
to
@type
, type/language value to
@reverse
, and append @set
to containers.
- 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:
- If
@index
is a not key in value, then
append @list
to containers.
- Initialize list to the array associated
with the key
@list
in value.
- Initialize common type and common language to null. If
list is empty, set common language to
default language.
- For each item in list:
- Initialize item language to
@none
and
item type to @none
.
- If item contains the key
@value
:
- If item contains the key
@language
,
then set item language to its associated
value.
- Otherwise, if item contains the key
@type
, set item type to its
associated value.
- Otherwise, set item language to
@null
.
- Otherwise, set item type to
@id
.
- If common language is null, set it
to item language.
- Otherwise, if item language does not equal
common language and item contains the
key
@value
, then set common language
to @none
because list items have conflicting
languages.
- If common type is null, set it
to item type.
- Otherwise, if item type does not equal
common type, then set common type
to
@none
because list items have conflicting
types.
- 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.
- If common language is null, set it to
@none
.
- If common type is null, set it to
@none
.
- If common type is not
@none
then set
type/language to @type
and
type/language value to common type.
- Otherwise, set type/language value to
common language.
- Otherwise:
- If value is a value object:
- If value contains the key
@language
and does not contain the key @index
,
then set type/language value to its associated
value and append @language
to
containers.
- Otherwise, if value contains the key
@type
, then set type/language value to
its associated value and set type/language to
@type
.
- Otherwise, set type/language to
@type
and set type/language value to @id
.
- Append
@set
to containers.
- 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.
- 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.
- 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.
- If type/language value is
@reverse
, append
@reverse
to preferred values.
- If type/language value is
@id
or @reverse
and value has an @id
member:
- If the result of using the
IRI compaction algorithm,
passing active context, inverse context,
the value associated with the
@id
key in value for
iri, true for vocab, and
true for document relative has a
term definition in the active context
with an IRI mapping that equals the value associated
with the @id
key in value,
then append @vocab
, @id
, and
@none
, in that order, to preferred values.
- Otherwise, append
@id
, @vocab
, and
@none
, in that order, to preferred values.
- Otherwise, append type/language value and
@none
, in
that order, to preferred values.
- Initialize term to the result of the
Term Selection algorithm, passing
inverse context, iri, containers,
type/language, and preferred values.
- If term is not null, return term.
- At this point, there is no simple term that iri
can be compacted to. If vocab is true and
active context has a vocabulary mapping:
- If iri begins with the
vocabulary mapping's value
but is longer, then initialize suffix to the substring
of iri that does not match. If suffix does not
have a term definition in active context,
then return suffix.
- The iri 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
tore the created compact IRI, if any.
- For each key term and value term definition in
the active context:
- If the term contains a colon (
:
),
then continue to the next term because
terms with colons can't be
used as prefixes.
- If the term definition is null,
its IRI mapping equals iri, or its
IRI mapping is not a substring at the beginning of
iri, the term cannot be used as a prefix
because it is not a partial match with iri.
Continue with the next term.
- Initialize candidate by concatenating term,
a colon (
:
), and the substring of iri
that follows after the value of the
term definition's
IRI mapping.
- If either compact IRI is null or 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 iri and value is null,
set compact IRI to candidate.
- If compact IRI is not null, return compact IRI.
- If vocab is false then
transform iri to a relative IRI using
the document's base IRI.
- Finally, return iri as is.
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 mappings
and which type mapping or language mapping would
be best used to express the value.
Algorithm
This algorithm has five required inputs. They are:
an inverse context, a keyword or IRI
iri, an array containers that represents an
ordered list of preferred container mappings,
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.
- Initialize container map to the value associated with
iri in the inverse context.
- For each item container in containers:
- If container is not a key in container map, then
there is no term with a matching
container mapping for it, so continue to the next
container.
- Initialize type/language map to the value associated
with the container member in container map.
- Initialize value map to the value associated
with type/language member in type/language map.
- For each item in preferred values:
- If item is not a key in value map,
then there is no term with a matching
type mapping or language mapping,
so continue to the next item.
- Otherwise, a matching term has been found, return the value
associated with the item member in
value map.
- No matching term has been found. Return null.
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.
Algorithm
This algorithm has four required inputs: an active context, an
inverse context, an active property, and a value
to be compacted.
- Initialize number members to the number of members
value contains.
- If value has an
@index
member and the
container mapping associated to active property
is set to @index
, decrease number members by
1
.
- If number members is greater than
2
, return
value as it cannot be compacted.
- If value has an
@id
member:
- If number members 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
member for iri.
- Otherwise, if number members 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
member for iri, and
true for vocab.
- Otherwise, return value as is.
- Otherwise, if value has an
@type
member whose
value matches the type mapping of active property,
return the value associated with the @value
member
of value.
- Otherwise, if value has an
@language
member whose
value matches the language mapping of
active property, return the value associated with the
@value
member of value.
- Otherwise, if number members equals
1
and either
the value of the @value
member 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
member.
- Otherwise, return value as is.
Flattening Algorithms
Flattening Algorithm
This algorithm flattens an expanded JSON-LD document by collecting all
properties of a node in a single JSON object
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.
Algorithm
The algorithm takes two input variables, an element to flatten and
an optional context used to compact the flattened document. If not
passed, context is set to null.
This algorithm generates new blank node identifiers
and relabels existing blank node identifiers.
The used Generate Blank Node Identifier algorithm
keeps an identifier map and a counter to ensure consistent
relabeling and avoid collisions. Thus, before this algorithm is run,
the identifier map is reset and the counter is initialized
to 0
.
- Initialize node map to a JSON object consisting of
a single member whose key is
@default
and whose value is
an empty JSON object.
- Perform the Node Map Generation algorithm, passing
element and node map.
- Initialize default graph to the value of the
@default
member of node map, which is a JSON object representing
the default graph.
- For each key-value pair graph name-graph in node map
where graph name is not
@default
, perform the following steps:
- If default graph does not have a graph name member, create
one and initialize its value to a JSON object consisting of an
@id
member whose value is set to graph name.
- Reference the value associated with the graph name member in
default graph using the variable entry.
- Add an
@graph
member to entry and set it to an
empty array.
- For each id-node pair in graph ordered by id,
add node to the
@graph
member of entry,
unless the only member of node is @id
.
- Initialize an empty array flattened.
- For each id-node pair in default graph ordered by id,
add node to flattened,
unless the only member of node is
@id
.
- If context is null, return flattened.
- Otherwise, return the result of compacting flattened according the
Compaction algorithm passing context
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.
Node Map Generation
This algorithm creates a JSON object 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 a member for every graph in the document whose
value is another object with a member for every node represented in the document.
The default graph is stored under the @default
member, all other graphs are
stored under their graph name.
Algorithm
The algorithm takes as input an expanded JSON-LD document element and a reference to
a JSON object node map. Furthermore it has the optional parameters
active graph (which defaults to @default
), an active subject,
active property, and a reference to a JSON object list. If
not passed, active subject, active property, and list are
set to null.
- If element is an array, process each item in element
as follows and then return:
- Run this algorithm recursively by passing item for element,
node map, active graph, active subject,
active property, and list.
- Otherwise element is a JSON object. Reference the
JSON object which is the value of the active graph
member of node map using the variable graph. If the
active subject is null, set node to null
otherwise reference the active subject member of graph using the
variable node.
- If element has an
@type
member, perform for each
item the following steps:
- If item is a blank node identifier, replace it with a newly
generated blank node identifier
passing item for identifier.
- If element has an
@value
member, perform the following steps:
- If list is null:
- If node does not have an active property member,
create one and initialize its value to an array
containing element.
- Otherwise, compare element against every item in the
array associated with the active property
member of node. If there is no item equivalent to element,
append element to the array. Two
JSON objects are considered
equal if they have equivalent key-value pairs.
- Otherwise, append element to the
@list
member of list.
- Otherwise, if element has an
@list
member, perform
the following steps:
- Initialize a new JSON object result consisting of a single member
@list
whose value is initialized to an empty array.
- Recursively call this algorithm passing the value of element's
@list
member for element, active graph,
active subject, active property, and
result for list.
- Append result to the the value of the active property member
of node.
- Otherwise element is a node object, perform
the following steps:
- If element has an
@id
member, set id
to its value and remove the member from element. If id
is a blank node identifier, replace it with a newly
generated blank node identifier
passing id for identifier.
- Otherwise, set id to the result of the
Generate Blank Node Identifier algorithm
passing null for identifier.
- If graph does not contain a member id, create one and initialize
its value to a JSON object consisting of a single member
@id
whose
value is id.
- If active property is not null, perform the following steps:
- Create a new JSON object reference consisting of a single member
@id
whose value is id.
- If list is null:
- If node does not have an active property member,
create one and initialize its value to an array
containing reference.
- Otherwise, compare reference against every item in the
array associated with the active property
member of node. If there is no item equivalent to reference,
append reference to the array. Two
JSON objects are considered
equal if they have equivalent key-value pairs.
- Otherwise, append element to the
@list
member of list.
- Reference the value of the id member of graph using the
variable node.
- If element has an
@type
key, append
each item of its associated array to the
array associated with the @type
key of
node unless it is already in that array. Finally
remove the @type
member from element.
- If element has an
@index
member, set the @index
member of node to its value. If node has already an
@index
member with a different value, a
conflicting indexes
error has been detected and processing is aborted. Otherwise, continue by
removing the @index
member from element.
- If element has an
@reverse
member:
- Create a JSON object referenced node with a single member
@id
whose
value is id.
- Set reverse map to the value of the
@reverse
member of
element.
- For each key-value pair property-values in reverse map:
- For each value of values:
- If value has a property member, append referenced node to
its value; otherwise create a property member whose value is an
array containing referenced node.
- Recursively invoke this algorithm passing value for
element, node map, and active graph.
- Remove the
@reverse
member from element.
- If element has an
@graph
member, recursively invoke this
algorithm passing the value of the @graph
member for element,
node map, and id for active graph before removing
the @graph
member from element.
- Finally, for each key-value pair property-value in element ordered by
property perform the following steps:
- If property is a blank node identifier, replace it with a newly
generated blank node identifier
passing property for identifier.
- If node does not have a property member, create one and initialize
its value to an empty array.
- Recursively invoke this algorithm passing value for element,
node map, active graph, id for active subject,
and property for active property.
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.
Algorithm
The algorithm takes a single input variable identifier which may
be null. Between its executions, the algorithm needs to
keep an identifier map to relabel existing
blank node identifiers
consistently and a counter to generate new
blank node identifiers. The
counter is initialized to 0
by default.
- If identifier is not null and has an entry in the
identifier map, return the mapped identifier.
- Otherwise, generate a new blank node identifier by concatenating
the string
_:b
and counter.
- Increment counter by
1
.
- If identifier is not null, create a new entry
for identifier in identifier map and set its value
to the new blank node identifier.
- Return the new blank node identifier.
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 JSON object elements.
Throughout this section, the following vocabulary
prefixes are used in
compact IRIs:
Prefix |
IRI |
rdf |
http://www.w3.org/1999/02/22-rdf-syntax-ns# |
rdfs |
http://www.w3.org/2000/01/rdf-schema# |
xsd |
http://www.w3.org/2001/XMLSchema# |
Deserialize 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
RDF triples that would have contained blank nodes as properties are
discarded when interpreting JSON-LD as RDF. However, if there is a
desire to retain the information contained in these triples,
three work-arounds are available: (a)
the user may set the produce extended RDF flag in the
JSON-LD-RDF Serializer/Deserializer,
to produce an extended
(non-standard) form of RDF that includes these triples; (b)
special purpose JSON-LD-RDF Serializers/Deserializers
can convert such
blank nodes to IRIs
by minting new "Skolem IRIs" as per
Replacing Blank Nodes with IRIs
of [[RDF11-CONCEPTS]]; or (c) the JSON-LD author can avoid the creation
of blank node properties by providing a context that maps those
properties to IRIs such as relative IRIs.
Note: This feature is
"at risk" and
may be removed from this specification based on feedback. Please send feedback to
public-rdf-comments@w3.org.
For the current status see
features "at risk" in JSON-LD 1.0
RDF graphs do not allow blank nodes to be used
as an RDF predicate, while JSON-LD does.
Unless the produce extended RDF flag is set, this algorithm will exclude
triples including a blank node RDF predicate.
Algorithm
The algorithm takes a JSON-LD document element and returns an
RDF dataset. Unless the produce extended RDF flag
is set to true, RDF triples
containing a blank node predicate
are excluded from output.
This algorithm generates new blank node identifiers
and relabels existing blank node identifiers.
The used Generate Blank Node Identifier algorithm
keeps an identifier map and a counter to ensure consistent
relabeling and avoid collisions. Thus, before this algorithm is run,
the identifier map is reset and the counter is initialized
to 0
.
- Expand element according to the
Expansion algorithm.
- Generate a node map according to the
Node Map Generation algorithm.
- Initialize an empty RDF dataset dataset.
- For each graph name and graph in node map
ordered by graph name:
- Initialize triples as an empty array.
- For each subject and node in graph ordered
by subject:
- For each property and values in node
ordered by property:
- If property is
@type
, then for each
type in values, append a triple
composed of subject, rdf:type
,
and type to triples.
- Otherwise, if property is a keyword
continue to the next property-values pair.
- Otherwise, if property is a blank node identifier and
the produce extended RDF flag is not true,
continue to the next property-values pair.
- Otherwise, property is an IRI or
blank node identifier. For each item
in values:
- If item is a list object, initialize
list triples as an empty array and
list head to the result of the List Conversion algorithm, passing
the value associated with the
@list
key from
item and list triples. Append first a
triple composed of subject,
property, and list head to triples and
finally append all triples from
list triples to triples.
- Otherwise, item is a value object
or a node object. Append a triple
composed of subject, property, and
the result of using the
Object to RDF Conversion algorithm
passing item to triples.
- If graph name is
@default
, add
triples to the default graph in dataset.
- Otherwise, create a named graph in dataset
composed of graph name and add triples.
- Return dataset.
Object to RDF Conversion
This algorithm takes a node object or value object
and transforms it into an
RDF resource
to be used as the object of an RDF triple.
Algorithm
The algorithm takes as its sole argument item which must be
either a value object or node object.
- If item is a node object return the
IRI or blank node identifier associated
with its
@id
member.
- Otherwise, item is a value object. Initialize
value to the value associated with the
@value
member in item.
- Initialize datatype to the value associated with the
@type
member of item or null if
item does not have such a member.
- If value is true or
false, set value to the string
true
or false
which is the
canonical lexical form as described in
Data Round Tripping
If datatype is null, set it to
xsd:boolean
.
- 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
Data Round Tripping.
If datatype is null, set it to
xsd:double
.
- 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
Data Round Tripping.
If datatype is null, set it to
xsd:integer
.
- Otherwise, if datatype is null, set it to
xsd:string
or rdf:langString
, depending on if
item has an @language
member.
- Initialize literal as an RDF literal using
value and datatype. If item has an
@language
member, add the value associated with the
@language
key as the language tag of literal.
- Return literal.
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 [[!RDF-MT]].
Algorithm
The algorithm takes two inputs: an array list
and an empty array list triples used for returning
the generated triples.
- If list is empty, return
rdf:nil
.
- Otherwise, create an array bnodes composed of a
newly generated blank node identifier
for each entry in list.
- Initialize an empty array list triples.
- For each pair of subject from bnodes and item from list:
- Append a triple composed of subject,
rdf:first
, and the result of using th
Object to RDF Conversion algorithm
passing item to list triples.
- 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.
- Return the first blank node from bnodes or
rdf:nil
if bnodes is empty.
Serialize from RDF Algorithm
This algorithm serializes an RDF dataset consisting of a
default graph and zero or more
named graphs into a JSON-LD document.
Algorithm
The algorithm takes two required inputs: an RDF dataset and a flag
use native types that defaults to false.
- Initialize default graph to an empty JSON object.
- Initialize graph map to a JSON object consisting
of a single member
@default
whose value references
default graph.
- For each graph in RDF dataset:
- If graph is the default graph,
set name to
@default
, otherwise to the
graph name associated with graph.
- If graph map has no name member, create one and set
its value to an empty JSON object.
- If graph is not the default graph and
default graph does not have a name member,
create such a member and initialize its value to a new
JSON object with a single member
@id
whose value is name.
- Reference the value of the name member in graph map
using the variable node map.
- For each RDF triple in graph
consisting of subject, predicate, and object:
- If node map does not have a subject member,
create one and initialize its value to a new JSON object
consisting of a single member
@id
whose value is
set to subject.
- Reference the value of the subject member in node map
using the variable node.
- If object is an IRI or blank node identifier,
and node map does not have an object member,
create one and initialize its value to a new JSON object
consisting of a single member
@id
whose value is
set to object.
- If predicate equals
rdf:type
, and object
is an IRI or blank node identifier,
append object to the value of the @type
member of node; unless such an item already exists.
If no such member exists, create one
and initialize it to an array whose only item is
object. Finally, continue to the next
RDF triple.
- Set value to the result of using the
RDF to Object Conversion algorithm,
passing object and use native types.
- If node does not have an predicate member, create one
and initialize its value to an empty array.
- If there is no item equivalent to value in the array
associated with the predicate member of node, append a
reference to value to the array. Two JSON objects
are considered equal if they have equivalent key-value pairs.
- If object is a blank node identifier or IRI,
it might represent the a list node:
- If the object member of node map has no
usages
member, create one and initialize it to
an empty array.
- Reference the
usages
member of the object
member of node map using the variable usages.
- Append a new JSON object consisting of three
members,
node
, property
, and value
to the usages array. The node
member
is set to a reference to node, property
to predicate,
and value
to a reference to value.
- For each name and graph object in graph map:
- If graph object has no
rdf:nil
member, continue
with the next name-graph object pair as the graph does
not contain any lists that need to be converted.
- Initialize nil to the value of the
rdf:nil
member
of graph object.
- For each item usage in the
usages
member of
nil, perform the following steps:
- Initialize node to the value of the value of the
node
member of usage, property to
the value of the property
member of usage,
and head to the value of the value
member
of usage.
- Initialize two empty arrays list
and list nodes.
- If property equals
rdf:rest
, the value
associated to the usages
member of node has
exactly 1 entry, node has a rdf:first
and
rdf:rest
property, both of which have as value an
array consisting of a single element, and node
has no other members apart from an optional @type
member whose value is an array with a single item equal to
rdf:List
, node represents a well-formed list
node. Continue with the following steps:
- Append the only item of
rdf:first
member of
node to the list array.
- Append the value of the
@id
member of
node to the list nodes array.
- Initialize node usage to the only item of the
usages
member of node.
- Set node to the value of the
node
member
of node usage, property to the value of the
property
member of node usage, and
head to the value of the value
member
of node usage.
- If the
@id
member of node is a
blank node identifier, continue to look for
the head of the list by jumping to
step 4.3.3.
- If property equals
rdf:first
, i.e., the
detected list is nested inside another list
- and the value of the
@id
of node equals
rdf:nil
, i.e., the detected list is empty,
continue with the next usage item. The
rdf:nil
node cannot be converted to a
list object as it would result in a list of
lists, which isn't supported.
- Otherwise, the list consists of at least one item. We preserve the
head node and transform the rest of the linked list to a
list object.
- Set head id to the value of the
@id
member of head.
- Set head to the value of the head id member of
graph object so that all it's properties can be accessed.
- Then, set head to the the only item in the value of the
rdf:rest
member of head.
- Finally, remove the last item of the list array
and the last item of the list nodes array.
- Remove the
@id
member from head.
- Reverse the order of the list array.
- Add a
@list
member to head and initialize
its value to the the list array.
- For each item node id in list nodes, remove the
node id member from graph object.
- Initialize an empty array result.
- For each subject and node in default graph
ordered by subject:
- If graph map has a subject member:
- Add a
@graph
member to node and initialize
its value to an empty array.
- For each key-value pair s-n in the the subject
member of graph map ordered by s, append n
to the
@graph
member of node after
removing its usages
member, unless the only
remaining member of n is @id
.
- Append node to result after removing its
usages
member, unless the only remaining member of
node is @id
.
- Return result.
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.
Algorithm
This algorithm takes two required inputs: a value to be converted
to a JSON object and a flag use native types.
- If value is an an IRI or a
blank node identifier, return a new JSON object
consisting of a single member
@id
whose value is set to
value.
- Otherwise value is an
RDF literal:
- Initialize a new empty JSON object result.
- Initialize converted value to value.
- Initialize type to null
- If use native types is true
- If the
datatype IRI
of value equals
xsd:string
, set
converted value to the
lexical form
of value.
- 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
.
- 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.
- Otherwise, if value is a
language-tagged string
add a member
@language
to result and set its value to the
language tag
of value.
- Otherwise, set type to the
datatype IRI
of value, unless it equals
xsd:string
which is ignored.
- Add a member
@value
to result whose value
is set to converted value.
- If type is not null, add a member
@type
to result whose value is set to type.
- Return result.
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 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 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:
The canonical lexical form of a double, i.e., a
number with a non-zero fractional part 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-1985]] 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:
The canonical lexical form of the boolean
values true and false are the strings
true
and false
.
When JSON-native numbers are deserialized
to RDF, lossless data round-tripping cannot be guaranteed, as rounding
errors might occur. When serializing
RDF to 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 [[RFC4627]]
does not limit the value space of numbers
either, concrete implementations typically do have a limited value
space.
To ensure lossless round-tripping the
Serializing from RDF algorithm
specifies a use native types 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 use native types 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.
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. A conformant JSON-LD API Implementation MUST
implement the entirety of the following API.
The JSON-LD API uses Promises to represent
the result of the various asynchronous operations.
Promises are defined in
section 4 Promises
of [[!DOM-WHATWG]].
Note: This feature is
"at risk" and may
be removed or modified heavily from the feature described in this specification
based on reviewer feedback. Please send feedback to
public-rdf-comments@w3.org.
For the current status see
features "at risk" in JSON-LD 1.0
The JSON-LD API specification currently only refers to the "Promise" interface and does not attempt to provide any details on the specific implementation of Promises. That is, it does not reference whether or not '.then()' must be specified. This is done in order to allow for some implementation flexibility in the event the DOM Promises spec changes. The editors of the WHATWG DOM specification have asserted that the Promise interface is ready to be incorporated into specifications. The issue relates to how to properly refer to a spec living in the WHATWG as a living standard as well as how to ensure that the interface provided by the spec is stable.
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 conformant
JSON-LD API Implementations
MUST 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.
- Promise compact()
-
Compacts the given input using the
context according to the steps in the
Compaction algorithm:
- Create a new Promise promise and return it. The
following steps are then executed asynchronously.
- If the passed input is a DOMString
representing the IRI of a remote document, dereference it.
If the retrieved document's content type is neither
application/json
,
nor application/ld+json
, nor any other media type using a
+json
suffix as defined in [[RFC6839]]
or if the document cannot be parsed as JSON, reject the promise passing an
loading document failed
error.
- Initialize a new empty active context. The base IRI
of the active context is set to the IRI of the currently being processed
document, if available; otherwise to null. If set, the
compactArrays
overrides the base IRI.
- If an
expandContext
has been passed, update the active context using the
Context Processing algorithm, passing the
expandContext
as local context.
- If the input has been retrieved, the response has an HTTP Link Header [[!RFC5988]]
using the
http://www.w3.org/ns/json-ld#context
link relation
and a content type of application/json
or any media type
with a +json
suffix as defined in [[RFC6839]] except
application/ld+json
, update the active context using the
Context Processing algorithm, passing the
context referenced in the HTTP Link Header as local context. The
HTTP Link Header is ignored for documents served as application/ld+json
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.
- Set expanded to the result of using the
Expansion algorithm, passing the
active context and input as element.
- Set compacted to the result of using the
Compaction algorithm, passing
context, expanded as element, and if passed, the
compactArrays
flag in options.
- Fulfill the promise passing compacted.
- any input
- The JSON-LD object or array of JSON-LD objects to perform the compaction upon or an
IRI referencing the JSON-LD document to compact.
- JsonLdContext context
- The context to use when compacting the
input
;
it can be specified by using a JSON object, an
IRI, or an array consisting of
JSON objects and IRIs.
- optional JsonLdOptions options
- A set of options to configure the algorithms. This allows, e.g.,
to set the input document's base IRI.
- Promise expand()
-
Expands the given input according to
the steps in the Expansion algorithm:
- Create a new Promise promise and return it. The
following steps are then executed asynchronously.
- If the passed input is a DOMString
representing the IRI of a remote document, dereference it.
If the retrieved document's content type is neither
application/json
,
nor application/ld+json
, nor any other media type using a
+json
suffix as defined in [[RFC6839]], reject the promise passing an
loading document failed
error.
- Initialize a new empty active context. The base IRI
of the active context is set to the IRI of the currently being processed
document, if available; otherwise to null. If set, the
compactArrays
overrides the base IRI.
- If an
expandContext
has been passed, update the active context using the
Context Processing algorithm, passing the
expandContext
as local context.
- If the input has been retrieved, the response has an HTTP Link Header [[!RFC5988]]
using the
http://www.w3.org/ns/json-ld#context
link relation
and a content type of application/json
or any media type
with a +json
suffix as defined in [[RFC6839]] except
application/ld+json
, update the active context using the
Context Processing algorithm, passing the
context referenced in the HTTP Link Header as local context. The
HTTP Link Header is ignored for documents served as application/ld+json
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.
- Set expanded to the result of using the
Expansion algorithm, passing the
active context and input as element.
- Fulfill the promise passing expanded.
- any input
- The JSON-LD object or array of JSON-LD objects to perform the expansion upon or an
IRI referencing the JSON-LD document to expand.
- optional JsonLdOptions options
- A set of options to configure the used algorithms such. This allows, e.g.,
to set the input document's base IRI.
- Promise flatten()
-
Flattens the given input and
compacts it using the passed context
according to the steps in the Flattening algorithm:
- Create a new Promise promise and return it. The
following steps are then executed asynchronously.
- If the passed input is a DOMString
representing the IRI of a remote document, dereference it.
If the retrieved document's content type is neither
application/json
,
nor application/ld+json
, nor any other media type using a
+json
suffix as defined in [[RFC6839]], reject the promise passing an
loading document failed
error.
- Initialize a new empty active context. The base IRI
of the active context is set to the IRI of the currently being processed
document, if available; otherwise to null. If set, the
compactArrays
overrides the base IRI.
- If an
expandContext
has been passed, update the active context using the
Context Processing algorithm, passing the
expandContext
as local context.
- If the input has been retrieved, the response has an HTTP Link Header [[!RFC5988]]
using the
http://www.w3.org/ns/json-ld#context
link relation
and a content type of application/json
or any media type
with a +json
suffix as defined in [[RFC6839]] except
application/ld+json
, update the active context using the
Context Processing algorithm, passing the
context referenced in the HTTP Link Header as local context. The
HTTP Link Header is ignored for documents served as application/ld+json
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.
- Set expanded to the result of using the
Expansion algorithm, passing the
active context and input as element.
- Initialize an empty identifier map and a counter (set to
0
)
to be used by the
Generate Blank Node Identifier algorithm.
- Set flattened to the result of using the
Flattening algorithm, passing
expanded as element, context, and if passed, the
compactArrays
flag in options (which is internally passed to the
Compaction algorithm).
- Fulfill the promise passing flattened.
- any input
- The JSON-LD object or array of JSON-LD objects or an IRI
referencing the JSON-LD document to flatten.
- optional JsonLdContext? context
- The context to use when compacting the flattened
input
;
it can be specified by using a JSON object, an
IRI, or an array consisting of JSON objects
and IRIs. If not
passed or null is passed, the result will not be compacted
but kept in expanded form.
- optional JsonLdOptions options
- A set of options to configure the used algorithms such. This allows, e.g.,
to set the input document's base IRI.
The JsonLdContext type is used to refer to a value that
that may be a JSON object, an IRI, or an
array of JSON objects and IRIs.
The JsonLdOptions type is used to pass various options to the
JsonLdProcessor methods.
- DOMString? base
- The base IRI to use when expanding or compacting the document. If set, this overrides
the input document's IRI.
- boolean compactArrays = true
- 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.
- LoadDocumentCallback documentLoader = null
- The callback of the loader to be used to retrieve remote documents and contexts.
If specified, it MUST be used to retrieve remote documents and contexts; otherwise,
if not specified, the processor's built-in loader MUST be used.
- (object? or DOMString) expandContext = null
- A context that is used to initialize the active context when expanding a document.
- DOMString processingMode = "json-ld-1.0"
- If set to
json-ld-1.0
, the JSON-LD processor 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.
Remote Document and Context Retrieval
Developers can utilize a callback to control how remote documents and contexts are retrieved
by JSON-LD API Implementations.
This section details the parameters of that callback and the data structure
used to return the retrieved context.
RemoteDocument
The RemoteDocument type is used by a LoadDocumentCallback
to return information about a remote document or context.
- DOMString contextUrl = null
- If available, the value of the HTTP Link Header [[!RFC5988]] 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 MUST be 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 MUST be rejected with
a JsonLdError whose code is set to
multiple context link headers
.
- DOMString documentUrl
- The final URL of the loaded document. This is important
to handle HTTP redirects properly.
- any document
- The retrieved document. This can either be the raw payload or the already
parsed document.
Error Handling
This section describes the datatype definitions used within the
JSON-LD API for error handling.
JsonLdError
The JsonLdError type is used to report processing errors.
- JsonLdErrorCode code
- a string representing the particular error type, as described in
the various algorithms in this document.
- DOMString? message = null
- an optional error message containing additional debugging information.
The specific contents of error messages are outside the scope of this
specification.
JsonLdErrorCode
The JsonLdErrorCode represents the collection of valid JSON-LD error
codes.
- loading document failed
- The document could not be loaded or parsed as JSON.
- list of lists
- A list of lists was detected. List of lists are not supported in
this version of JSON-LD due to the algorithmic complexity associated
with deserialization to RDF.
- invalid @index value
- An
@index
member was encountered whose value was
not a string.
- conflicting indexes
- Multiple conflicting indexes have been found for the same node.
- invalid @id value
- An
@id
member was encountered whose value was not a
string.
- invalid local context
- In invalid local context was detected.
- multiple context link headers
- Multiple HTTP Link Headers [[!RFC5988]] using the
http://www.w3.org/ns/json-ld#context
link relation
have been detected.
- loading remote context failed
- There was a problem encountered loading a remote context.
- invalid remote context
- No valid context document has been found for a referenced,
remote context.
- recursive context inclusion
- A cycle in remote context inclusions has been detected.
- invalid base IRI
- An invalid base IRI has been detected, i.e., it is
neither an absolute IRI nor null.
- invalid vocab mapping
- An invalid vocabulary mapping has been detected, i.e.,
it is neither an absolute IRI nor null.
- invalid default language
- The value of the default language is not a string
or null and thus invalid.
- keyword redefinition
- A keyword redefinition has been detected.
- invalid term definition
- An invalid term definition has been detected.
- invalid reverse property
- An invalid reverse property definition has been detected.
- invalid IRI mapping
- A local context contains a term that has
an invalid or missing IRI mapping.
- cyclic IRI mapping
- A cycle in IRI mappings has been detected.
- invalid keyword alias
- An invalid keyword alias definition has been
encountered.
- invalid type mapping
- An
@type
member in a term definition
was encountered whose value could not be expanded to an
absolute IRI.
- invalid language mapping
- An
@language
member in a term definition
was encountered whose value was neither a string nor
null and thus invalid.
- colliding keywords
- Two properties which expand to the same keyword have been detected.
This might occur if a keyword and an an alias thereof
are used at the same time.
- invalid container mapping
- An
@container
member was encountered whose value was
not one of the following strings:
@list
, @set
, or @index
.
- invalid type value
- An invalid value for an
@type
member has been detected,
i.e., the value was neither a string nor an array
of strings.
- invalid value object
- A value object with disallowed members has been
detected.
- invalid value object value
- An invalid value for the
@value
member of a
value object has been detected, i.e., it is neither
a scalar nor null.
- 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 typed value
- A typed value with an invalid type was detected.
- invalid set or list object
- A set object or list object with
disallowed members has been detected.
- invalid language map value
- An invalid value in a language map
has been detected. It has to be a string or an array of
strings.
- compaction to list of lists
- The compacted document contains a list of lists as multiple
lists have been compacted to the same term.
- 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 value
- An invalid value for an
@reverse
member has been detected,
i.e., the value was not a JSON object.
- 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.