CARVIEW |
JSON-LD 1.0 Processing Algorithms and API
Final Community Group Specification 28 March 2013
- Latest editor's draft:
- https://dvcs.w3.org/hg/json-ld/raw-file/spec/latest/json-ld-api/index.html
- Test suite:
- https://json-ld.org/test-suite/
- Editors:
- Markus Lanthaler, Graz University of Technology
- Gregg Kellogg, Kellogg Associates
- Manu Sporny, Digital Bazaar
- Authors:
- Dave Longley, Digital Bazaar
- Gregg Kellogg, Kellogg Associates
- Markus Lanthaler, Graz University of Technology
- Manu Sporny, Digital Bazaar
This document is also available in this non-normative format: diff to previous version
Copyright © 2010-2013 the Contributors to the JSON-LD 1.0 Processing Algorithms and API Specification, published by the RDF Working Group under the W3C Community Final Specification Agreement (FSA). A human-readable summary is available.
Abstract
This specification defines an Application Programming Interface (API) and a set of algorithms for programmatic transformations of JSON-LD documents. By expressing the data in a way that is specifically tailored to a particular use case, the processing typically becomes much simpler.
Status of This Document
This specification was published by the RDF Working Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Final Specification Agreement (FSA) other conditions apply. Learn more about W3C Community and Business Groups.
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 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.
It is important for readers to understand that the scope of this document is currently under debate and new features may be added to the specification. Existing features may be modified heavily or removed entirely from the specification upon further review and feedback from the broader community. This is a work in progress and publication as a Working Draft does not require that all Working Group members agree on the content of the document.
There are a number of ways that one may participate in the development of this specification:
- 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: [email protected]
- Ad-hoc technical discussion primarily occurs on the public community mailing list: [email protected]
- 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.
Table of Contents
1. Introduction
This section is non-normative.
This document is a detailed specification for an Application Programming Interface for the JSON-LD syntax. The document is primarily intended for the following audiences:
- Developers that want an overview of the JSON-LD API.
- Web authors and developers that want a very detailed view of how a JSON-LD Implementation or a JSON-LD Processor's API operates.
- Software developers that want to implement the algorithms to transform JSON-LD documents.
To understand the basics in this specification you must first be familiar with JSON, which is detailed in [RFC4627]. You must also understand the JSON-LD Syntax [JSON-LD], which is the base syntax used by all of the algorithms in this document. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ECMA-262] and WebIDL [WEBIDL]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [RDF11-CONCEPTS].
2. Features
This section is non-normative.
The JSON-LD Syntax specification [JSON-LD] outlines a syntax that may be used 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.
The way JSON-LD allows Linked Data to be expressed in a way that is specifically tailored to a particular person or application is by providing a context. 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 conversion.
2.1 Expansion
This section is non-normative.
The algorithm that removes context is called expansion. Before performing any other transformations on a JSON-LD document, it is easiest to remove any context from it, localizing all information, and to make data structures more regular.
To get an idea of how context and data structuring affects the same data, here is an example of JSON-LD that uses only terms and is fairly compact:
{ "@context": { "name": "https://xmlns.com/foaf/0.1/name", "homepage": { "@id": "https://xmlns.com/foaf/0.1/homepage", "@type": "@id" } }, "@id": "https://me.markus-lanthaler.com/", "name": "Markus Lanthaler", "homepage": "https://www.markus-lanthaler.com/" }
The next input example uses one IRI to express a property and array to encapsulate another, but leaves the rest of the information untouched.
{ "@context": { "website": "https://xmlns.com/foaf/0.1/homepage" }, "@id": "https://me.markus-lanthaler.com/", "https://xmlns.com/foaf/0.1/name": "Markus Lanthaler", "website": { "@id": "https://www.markus-lanthaler.com/" } }
Note that both inputs are valid JSON-LD and both represent the same information. The difference is in their context information and in the data structures used. A JSON-LD processor can remove context and ensure that the data is more regular by employing expansion.
Expansion has two important goals: removing any contextual
information from the document, and ensuring all values are represented
in a regular form. These goals are accomplished by expanding all properties
to absolute IRIs and by expressing all
values in arrays in
expanded form. Expanded form is the most verbose
and regular way of expressing of values in JSON-LD; all contextual
information from the document is instead stored locally with each value.
Running the Expansion algorithm
(expand
operation) against the examples provided above results in the following output:
[ { "@id": "https://me.markus-lanthaler.com/", "https://xmlns.com/foaf/0.1/name": [ { "@value": "Markus Lanthaler" } ], "https://xmlns.com/foaf/0.1/homepage": [ { "@id": "https://www.markus-lanthaler.com/" } ] } ]
Note that in the output above all context definitions have been removed, all terms and compact IRIs have been expanded to absolute IRIs, and all JSON-LD values are expressed in arrays in expanded form. While the output is more verbose and difficult for a human to read, it establishes a baseline that makes JSON-LD processing easier because of its very regular structure.
2.2 Compaction
This section is non-normative.
While expansion removes context from a given input, compaction's primary function is to perform the opposite operation: to express a given input according to a particular context. Compaction applies a context that specifically tailors the way information is expressed for a particular person or application. This simplifies applications that consume JSON or JSON-LD by expressing the data in application-specific terms, and it makes the data easier to read by humans.
Compaction uses a developer-supplied context to shorten IRIs to terms or compact IRIs and JSON-LD values expressed in expanded form to simple values such as strings or numbers.
For example, assume the following expanded JSON-LD input document:
[ { "@id": "https://me.markus-lanthaler.com/", "https://xmlns.com/foaf/0.1/name": [ { "@value": "Markus Lanthaler" } ], "https://xmlns.com/foaf/0.1/homepage": [ { "@id": "https://www.markus-lanthaler.com/" } ] } ]
Additionally, assume the following developer-supplied JSON-LD context:
{ "@context": { "name": "https://xmlns.com/foaf/0.1/name", "homepage": { "@id": "https://xmlns.com/foaf/0.1/homepage", "@type": "@id" } } }
Running the Compaction Algorithm
(compact
operation) given the context supplied above against the JSON-LD input
document provided above would result in the following output:
{ "@context": { "name": "https://xmlns.com/foaf/0.1/name", "homepage": { "@id": "https://xmlns.com/foaf/0.1/homepage", "@type": "@id" } }, "@id": "https://me.markus-lanthaler.com/", "name": "Markus Lanthaler", "homepage": "https://www.markus-lanthaler.com/" }
Note that all IRIs have been compacted to
terms as specified in the context,
which has been injected into the output. While compacted output is
useful to humans, it is also used to generate structures that are easy to
program against. Compaction enables developers to map any expanded document
into an application-specific compacted document. While the context provided
above mapped https://xmlns.com/foaf/0.1/nam
to name
, it
could also have been mapped to any other term provided by the developer.
2.3 Flattening
This section is non-normative.
While expansion ensures that a document is in a uniform structure, flattening goes a step further to ensure that the shape of the data is deterministic. In expanded documents, the properties of a single node may be spread across a number of different JSON objects. By flattening a document, all properties of a node are collected in a single JSON object and all blank nodes are labeled with a blank node identifier. This may drastically simplify the code required to process JSON-LD data in certain applications.
For example, assume the following JSON-LD input document:
{ "@context": { "name": "https://xmlns.com/foaf/0.1/name", "knows": "https://xmlns.com/foaf/0.1/knows" }, "@id": "https://me.markus-lanthaler.com/", "name": "Markus Lanthaler", "knows": [ { "name": "Dave Longley" } ] }
Running the Flattening algorithm
(flatten
operation) with a context set to null to prevent compaction
returns the following document:
[ { "@id": "_:t0", "https://xmlns.com/foaf/0.1/name": [ { "@value": "Dave Longley" } ] }, { "@id": "https://me.markus-lanthaler.com/", "https://xmlns.com/foaf/0.1/name": [ { "@value": "Markus Lanthaler" } ], "https://xmlns.com/foaf/0.1/knows": [ { "@id": "_:t0" } ] } ]
Note how in the output above all properties of a node are collected in a
single JSON object and how the blank node representing
"Dave Longley" has been assigned the blank node identifier
_:t0
.
To make it easier for humans to read or for certain applications to process it, a flattened document can be compacted by passing a context. Using the same context as the input document, the flattened and compacted document looks as follows:
{ "@context": { "name": "https://xmlns.com/foaf/0.1/name", "knows": "https://xmlns.com/foaf/0.1/knows" }, "@graph": [ { "@id": "_:t0", "name": "Dave Longley" }, { "@id": "https://me.markus-lanthaler.com/", "name": "Markus Lanthaler", "knows": { "@id": "_:t0" } } ] }
Please note that the flattened and compacted result always explicitly
designates the default graph by the @graph
member in the
top-level JSON object.
2.4 RDF Conversion
This section is non-normative.
JSON-LD can be used to serialize data expressed in RDF as described in [RDF11-CONCEPTS]. This ensures that data can be round-tripped to and from any RDF syntax without any loss in fidelity.
For example, assume the following RDF input serialized in Turtle [TURTLE]:
<https://me.markus-lanthaler.com/> <https://xmlns.com/foaf/0.1/name> "Markus Lanthaler" . <https://me.markus-lanthaler.com/> <https://xmlns.com/foaf/0.1/homepage> <https://www.markus-lanthaler.com/> .
Using the Convert from RDF algorithm a developer could transform this document into expanded JSON-LD:
[ { "@id": "https://me.markus-lanthaler.com/", "https://xmlns.com/foaf/0.1/name": [ { "@value": "Markus Lanthaler" } ], "https://xmlns.com/foaf/0.1/homepage": [ { "@id": "https://www.markus-lanthaler.com/" } ] } ]
Note that the output above could easily be compacted using the technique outlined in the previous section. It is also possible to transform the JSON-LD document back to RDF using the Convert to RDF algorithm.
3. 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 two classes of products that can claim conformance to this specification: JSON-LD Implementations and JSON-LD Processors.
A conforming JSON-LD Implementation is a system capable of transforming JSON-LD documents according the algorithms defined in this specification.
A conforming JSON-LD Processor is a conforming JSON-LD Implementation
that exposes the Application Programming Interface (API) defined in this specification.
It MUST implement the json-ld-1.0
processing mode (for further details, see the
processingMode
option of JsonLdOptions
).
The algorithms in this specification are generally written with more concern for clarity than efficiency. Thus, JSON-LD Implementations and Processors may implement the algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.
This specification does not define how JSON-LD Implementations or Processors handle non-conforming input documents. This implies that JSON-LD Implementations or Processors MUST NOT attempt to correct malformed IRIs or language tags; however, they MAY issue validation warnings. IRIs are not modified other than converted between relative and absolute IRIs.
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.
4. 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 (or elements). Elements 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 specific markup is provided (see ).
- 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 JSON-LD Syntax specification [JSON-LD] in the section titled Syntax Tokens and Keywords.
- context
- A a set of rules for interpreting a JSON-LD document as specified in The Context of the [JSON-LD] specification.
- JSON-LD document
- A JSON-LD document is a serialization of a collection of JSON-LD 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 JSON-LD graph.
- default graph
- The default graph is the only graph in a JSON-LD document which has no graph name.
- JSON-LD 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 syntax 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 some other absolute IRI; in the case of JSON-LD this is the base location of the document.
- blank node
- A node in a JSON-LD graph that does not contain a de-referenceable identifier because it is either ephemeral in nature or does not contain information that needs to be linked to from outside of the JSON-LD graph.
- 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 of [BCP47], and is normalized to lowercase.
- list
- A list is an ordered sequence of IRIs, blank nodes, and JSON-LD values.
5. 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 is 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 JSON-LD 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
.
- it does not contain the
- 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.
6. Context Processing Algorithms
6.1 Context Processing Algorithm
When processing a JSON-LD data structure, each processing rule is applied using information provided by the active context. This section describes how to produce an active context.
The active context contains the active term definitions which specify how 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.
General Solution
This section is non-normative.
First we prepare a new active context result by cloning the current active context. Then we normalize the form the passed local context to an array. Local contexts may be in the form of a JSON object, a string, or an array containing a combination of the two. Finally we process each context contained in the local context array as follows.
If context is a string, it represents a reference to
a remote context. We dereference the remote context and replace context
with the value of the @context
key of the top-level object in the
retrieved JSON-LD document. If there's no such key, an invalid remote context has
been detected. Otherwise, we process context by recursively using
this algorithm ensuring that there is no cyclical reference.
If context is a JSON object, we first update the
base IRI, the vocabulary mapping, and the
default language by processing three specific keywords:
@base
, @vocab
, and @language
.
These are handled before any other keys in the local context because
they affect how the other keys are processed.
Then, for every other key in local context, we update the term definition in result. Since term definitions in a local context may themselves contain terms or compact IRIs, we may need to recurse. When doing so, we must ensure that there is no cyclical dependency, which is an error. After we have processed any term definition dependencies, we update the current term definition, which may be a keyword alias.
Finally, we return result as the new active context.
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.
- 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. - Initialize context no base to the result of cloning the active context.
- Remove the base IRI of context no base.
- Dereference context. If the dereferenced document has no
top-level JSON object with an
@context
member, aninvalid remote context
has been detected and processing is aborted; otherwise, set context to the value of that member. - Set context to the result of recursively calling this algorithm, passing context no base for active context, context for local context, and remote contexts.
- If context has no base IRI but result does, set the base IRI of context to the one of result.
- Overwrite result with context and 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:Issue 223: Feature at riskThis feature is at risk as the fact that a document may have multiple base IRIs is potentially confusing for developers. It is also being discussed whether relative IRIs are allowed as values of
@base
or whether the empty string should be used to explicitly specify that there isn't a base IRI, which could be used to ensure that relative IRIs remain relative when expanding.- 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.
If it is not an absolute IRI, an
invalid base IRI
error has been detected and processing is aborted.
- Initialize value to the value associated with the
- 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,
the vocabulary mapping of result is set
to value. If it is not an absolute IRI, an
invalid vocab mapping
error has been detected and processing is aborted.
- Initialize value to the value associated with the
- 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.
- Initialize value to the value associated with the
- 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.
6.2 Create Term Definition
This algorithm is called from the Context Processing algorithm to create a term definition in the active context for a term being processed in a local context.
General Solution
This section is non-normative.
Term definitions are created by parsing the information in the given local context for the given term. If the given term is a compact IRI, it may omit an IRI mapping by depending on its prefix having its own term definition. If the prefix is a key in the local context, then its term definition must first be created, through recursion, before continuing. Because a term definition can depend on other term definitions, a mechanism must be used to detect cyclical dependencies. The solution employed here uses a map, defined, that keeps track of whether or not a term has been defined or is currently in the process of being defined. This map is checked before any recursion is attempted.
After all dependencies for a term have been defined, the rest of the information in the local context for the given term is taken into account, creating the appropriate IRI mapping, container mapping, and type mapping or language mapping for the term.
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 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:
- Expand value by setting it to the result of using the IRI Expansion algorithm, passing active context, value, true for vocab, true for document relative, local context, and defined.
- If value is
@context
, aninvalid keyword alias
error has been detected and processing is aborted. - Set the IRI mapping for the term definition for term in active context to value, set the value associated with defined's key term to true, and return.
- 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
@reverse
:- If value contains an
@id
, an@type
, or an@language
, member, aninvalid reverse property
error has been detected and processing is aborted. - If the value associated with the
@reverse
key is not a string, aninvalid 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, true for document relative, local context, and defined. If the result is not an absolute IRI, i.e., it contains no colon (:
), aninvalid IRI mapping
error has been detected and processing is aborted. - Set the type mapping of definition to
@id
. - If value contains an
@container
member, set the container mapping of definition to@index
if that is the value of the@container
member; otherwise aninvalid reverse property
error has been detected (reverse properties only support 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.
- If value contains an
- Set the reverse property flag of definition to false.
- If value contains the key
@id
:- If the value associated with the
@id
key is not a string, aninvalid 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, true for document relative, local context, and defined.
- If the value associated with the
-
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
@type
:- Initialize type to the value associated with the
@type
key, which must be a string. Otherwise, aninvalid 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,
true for document relative,
local context, and defined. If the expanded type is
neither
@id
, nor@vocab
, nor an absolute IRI, aninvalid type mapping
error has been detected and processing is aborted. - Set the type mapping for definition to type.
- Initialize type to the value associated with the
- 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, aninvalid container mapping
error has been detected and processing is aborted. - Set the container mapping of definition to container.
- Initialize container to the value associated with the
- 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, aninvalid 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.
- Initialize language to the value associated with the
- Set the term definition of term in active context to definition and set the value associated with defined's key term to true.
6.3 IRI Expansion
In JSON-LD documents, some keys and values may represent IRIs. This section defines an algorithm for transforming a string that represents an IRI into an absolute IRI or blank node identifier. It also covers transforming keyword aliases into keywords.
IRI expansion may occur during context processing or during any of the other JSON-LD algorithms. If IRI expansion occurs during context processing, then the local context and its related defined map from the Context Processing algorithm are passed to this algorithm. This allows for term definition dependencies to be processed via the Create Term Definition algorithm.
General Solution
This section is non-normative.
In order to expand value to an absolute IRI, we must first determine if it is null, a term, a keyword alias, or some form of IRI. Based on what we find, we handle the specific kind of expansion; for example, we expand a keyword alias to a keyword and a term to an absolute IRI according to its IRI mapping in the active context. While inspecting value we may also find that we need to create term definition dependencies because we're running this algorithm during context processing. We can tell whether or not we're running during context processing by checking local context against null. We know we need to create a term definition in the active context when value is a key in the local context and the defined map does not have a key for value with an associated value of true. The defined map is used during Context Processing to keep track of which terms have already been defined or are in the process of being defined. We create a term definition by using the Create Term Definition algorithm.
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 not underscore (
_
) and suffix does not begin with double-forward-slash (//
), it may be a compact IRI:- 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.
- Split value into a prefix and suffix
at the first occurrence of a colon (
- 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.
7. Expansion Algorithms
7.1 Expansion Algorithm
This algorithm expands a JSON-LD document, such that all context definitions are removed, all terms and compact IRIs are expanded to absolute IRIs, blank node identifiers, or keywords and all JSON-LD values are expressed in arrays in expanded form.
General Solution
This section is non-normative.
Starting with its root element, we can process the JSON-LD document recursively, until we have a fully expanded result. When expanding an element, we can treat each one differently according to its type, in order to break down the problem:
- If the element is null, there is nothing to expand.
- Otherwise, if element is a scalar, we expand it according to the Value Expansion algorithm.
- Otherwise, if the element is an array, then we expand each of its items recursively and return them in a new array.
- Otherwise, element is a JSON object. We expand each of its keys, adding them to our result, and then we expand each value for each key recursively. Some of the keys will be terms or compact IRIs and others will be keywords or simply ignored because they do not have definitions in the context. Any IRIs will be expanded using the IRI Expansion algorithm.
Finally, after ensuring result is in an array, we return result.
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 active property is null or
- 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 alist 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
, aninvalid 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, aninvalid @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, aninvalid 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, aninvalid 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, aninvalid 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, aninvalid @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 active property is null or
- 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, aninvalid @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.
- If item is a value object or list object, an
- For each item in items:
- If result does not have an
- Continue with the next key from element.
- Initialize expanded value to the result of using this
algorithm recursively, passing active context,
- Unless expanded value is null, set the expanded property member of result to expanded value.
- Continue with the next key from element..
- If active property equals
- 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).
- item must be a string,
otherwise an
- 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.
- If item does not have the key
- 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.
- If item is a value object or list object, an
- If result has no
- 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 key is
- 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, aninvalid 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
, aninvalid 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 a string, aninvalid typed value
error has been detected and processing is aborted.
- The result must not contain any keys other than
- 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, aninvalid 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.
- The result must contain at most one other key and that
key must be
- 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.
- If result is an empty JSON object or contains
the keys
- 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.
7.2 Value Expansion
Some values in JSON-LD can be expressed in a compact form. These values are required to be expanded at times when processing JSON-LD documents. A value is said to be in expanded form after the application of this algorithm.
General Solution
This section is non-normative.
If active property has a type mapping in the
active context set to @id
or @vocab
,
a JSON object with a single member @id
whose
values is the result of using the
IRI Expansion algorithm on value
is returned.
Otherwise, the result will be a JSON object containing
an @value
member whose value is the passed value.
Additionally, an @type
member will be included if there is a
type mapping associated with the active property
or an @language
member if value is a
string and there is language mapping associated
with the active property.
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.
- If a language mapping is associated with
active property in active context,
add an
- Return result.
8. Compaction Algorithms
8.1 Compaction Algorithm
This algorithm compacts a JSON-LD document, such that the given context is applied. This must result in shortening any applicable IRIs to terms or compact IRIs, any applicable keywords to keyword aliases, and any applicable JSON-LD values expressed in expanded form to simple values such as strings or numbers.
General Solution
This section is non-normative.
Starting with its root element, we can process the JSON-LD document recursively, until we have a fully compacted result. When compacting an element, we can treat each one differently according to its type, in order to break down the problem:
- If the element is a scalar, it is already in compacted form, so we simply return it.
- If the element is an array, we compact each of its items recursively and return them in a new array.
- Otherwise element is a JSON object. The value
of each key in element is compacted recursively. Some of the keys will be
compacted, using the IRI Compaction algorithm,
to terms or compact IRIs
and others will be compacted from keywords to
keyword aliases or simply left
unchanged because they do not have definitions in the context.
Values will be converted to compacted form via the
Value Compaction algorithm. Some data
will be reshaped based on container mappings
specified in the context such as
@index
or@language
maps.
The final output is a JSON object with a @context
key, if a context was given, where the JSON object
is either result or a wrapper for it where result appears
as the value of an (aliased) @graph
key because result
contained two or more items in an array.
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 em>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, andcompactArrays
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, and expanded property for iri.
- Add a member alias to result whose value is set to compacted value and continue to the next expanded property.
- 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
- 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
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
- If the term definition for property in the
active context indicates that property is
a reverse property
- 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, and
@reverse
for iri. - Set the value of the alias member of result to compacted value and continue with the next expanded property from element.
- Initialize alias to the result of using the
IRI Compaction algorithm,
passing active context, inverse context, and
- Initialize compacted value to the result of using this
algorithm recursively, passing active context,
inverse context,
- 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, and expanded property for iri.
- 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 associated with the@index
key in expanded item as value.
- 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,
- 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 a key in result, then initialize map object to its associated value, otherwise initialize it to an empty JSON object.
- 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.
- If
- If expanded property is
- 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 context has been passed, add an
@context
member to result and set its value to
the passed context.
8.2 Inverse Context Creation
When there is more than one term that could be chosen to compact an IRI, it has to be ensured that the term selection is both deterministic and represents the most context-appropriate choice whilst taking into consideration algorithmic complexity.
In order to make term selections, the concept of an inverse context is introduced. An inverse context is essentially a reverse lookup table that maps container 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.
General Solution
This section is non-normative.
To create an inverse context for a given
active context, each term in the
active context is visited, ordered by length, shortest
first (ties are broken by choosing the lexicographically least
term). For each term, an entry is added to
the inverse context for each possible combination of
container mapping and type mapping
or language mapping that would legally match the
term. Illegal matches include differences between a
value's type mapping or language mapping and
that of the term. If a term has no
container mapping, type mapping, or
language mapping (or some combination of these), then it
will have an entry in the inverse context using the special
key @none
. This allows the
Term Selection algorithm to fall back
to choosing more generic terms when a more
specifically-matching term is not available for a particular
IRI and value combination.
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 has no container map 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.
- Reference the value associated with the
- 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.
- Reference the value associated with the
- 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.
- Reference the value associated with the
- 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.
- Reference the value associated with the
- Return result.
8.3 IRI Compaction
This algorithm compacts an IRI to a term or compact IRI, or a keyword to a keyword alias. A value that is associated with the IRI may be passed in order to assist in selecting the most context-appropriate term.
General Solution
This section is non-normative.
If the passed IRI is null, we simply return null. Otherwise, we first try to find a term that the IRI or keyword can be compacted to if it is relative to active context's vocabulary mapping. In order to select the most appropriate term, we may have to collect information about the passed value. This information includes whic container mappings would be preferred for expressing the value, and what its type mapping or language mapping is. For JSON-LD lists, the type mapping or language mapping will be chosen based on the most specific values that work for all items in the list. Once this information is gathered, it is passed to the Term Selection algorithm, which will return the most appropriate term to use.
If no term was found that could be used to compact the IRI, then an attempt is made to find a compact IRI to use. If there is no appropriate compact IRI, then, if the IRI is relative to active context's vocabulary mapping, then it is used. Otherwise, it is transformed to a relative IRI using the document's base IRI. Finally, if the IRI or keyword still could not be compacted, it is returned as is.
Algorithm
This algorithm takes three required inputs and three optional inputs.
The required inputs 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 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
.
- If item contains the key
- 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.
- Initialize item language to
- 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.
- If
- 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
.
- If value contains the key
- Otherwise, set type/language to
@type
and set type/language value to@id
. - Append
@set
to containers.
- If value is a value object:
- 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.
- If the result of using the
IRI compaction algorithm,
passing active context, inverse context,
the value associated with the
- 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.
- Initialize default language to
active context's
default language, if it has one, otherwise to
- At this point, there is no simple term that iri can be compacted to. Instead, try to create a compact IRI, starting by initializing compact IRI to null. This variable will be used to store the created compact IRI, if any.
- 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 the term contains a colon (
- If compact IRI is not null, return compact IRI.
- At this point, there is no compact IRI that iri
can be compacted to, so 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.
- If vocab is false then transform iri to a relative IRI using the document's base IRI.
- Finally, return iri as is.
8.4 Term Selection
This algorithm, invoked via the IRI Compaction algorithm, makes use of an active context's inverse context to find the term that is best used to compact an IRI. Other information about a value associated with the IRI is given, including which container mappings and which type mapping or language mapping would be best used to express the value.
General Solution
This section is non-normative.
The inverse context's entry for the IRI will be first searched according to the preferred container mappings, in the order that they are given. Amongst terms with a matching container mapping, preference will be given to those with a matching type mapping or language mapping, over those without a type mapping or language mapping. If there is no term with a matching container mapping then the term without a container mapping that matches the given type mapping or language mapping is selected. If there is still no selected term, then a term with no type mapping or language mapping will be selected if available. No term will be selected that has a conflicting type mapping or language mapping. Ties between terms that have the same mappings are resolved by first choosing the shortest terms, and then by choosing the lexicographically least term. Note that these ties are resolved automatically because they were previously resolved when the Inverse Context Creation algorithm was used to create the inverse context.
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.
8.5 Value Compaction
Expansion transforms all values into expanded form in JSON-LD. This algorithm performs the opposite operation, transforming a value into compacted form. This algorithm compacts a value according to the term definition in the given active context that is associated with the value's associated active property.
General Solution
This section is non-normative.
The value to compact has either an @id
or an
@value
member.
For the former case, if the type mapping of
active property is set to @id
or @vocab
and value consists of only of an @id
member and, if
if the container mapping of active property
is set to @index
, an @index
member, value
can be compacted to a string by returning the result of
using the IRI Compaction algorithm
to compact the value associated with the @id
member.
Otherwise, value cannot be compacted and is returned as is.
For the latter case, it might be possible to compact value
just into the value associated with the @value
member.
This can be done if the active property has a matching
type mapping or language mapping and there
is either no @index
member or the container mapping
of active property is set to @index
. It can
also be done if @value
is the only member in value
(apart an @index
member in case the container mapping
of active property is set to @index
) and
either its associated value is not a string, there is
no default language, or there is an explicit
null language mapping for the
active property.
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 by1
. - 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.
- If number members 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.
9. Flattening Algorithms
9.1 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.
General Solution
This section is non-normative.
First, a node map is generated using the Node Map Generation algorithm which collects all properties of a node in a single JSON object. In the next step, the node map is converted to a JSON-LD document in flattened document form. Finally, if a context has been passed, the flattened document is compacted using the Compaction algorithm before being returned.
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.
- 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.
- If default graph does not have a graph name member, create
one and initialize its value to a JSON object consisting of an
- Initialize an empty array flattened.
- For each id-node pair in default graph ordered by id, add node to flattened.
- If context is null, return flattened.
- Otherwise, return the result of compacting flattened according the
Compaction algorithm passing context
ensuring that the compaction result uses the
@graph
keyword (or its alias) at the top-level, even if the context is empty or if there is only one element to put in the@graph
array. This ensures that the returned document has a deterministic structure.
9.2 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.
General Solution
This section is non-normative.
The algorithm recursively runs over an expanded JSON-LD document to
collect all properties of a node
in a single JSON object. The algorithm constructs a
JSON object node map whose keys represent the
graph names used in the document
(the default graph is stored under the key @default
)
and whose associated values are JSON objects
which index the nodes in the
graph. If a
property's value is a node object,
it is replace by a node object consisting of only an
@id
member. If a node object has no @id
member or it is identified by a blank node identifier,
a new blank node identifier is generated. This relabeling
of blank node identifiers is
also be done for properties and values of
@type
.
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 graph has no member item, create one and initialize its
value to a JSON object consisting of a single member
@id
whose value is item.
- If element has an
@value
member, perform the following steps:- If list is null, merge element into the active property member of node; the resulting array must not contain any duplicate values.
- 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.
- Initialize a new JSON object result consisting of a single member
- 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, merge element into the active property member of node; the resulting array must not contain any duplicate values.
- Otherwise, append element to the
@list
member of list.
- Create a new JSON object reference consisting of a single member
- Reference the value of the id member of graph using the variable node.
- If element has an
@type
member, merge each of its values into the@type
member of node and finally remove the@type
member from element; the resulting array must not contain any duplicate values. - 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, aconflicting 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.
- For each value of values:
- Remove the
@reverse
member from element.
- Create a JSON object referenced node with a single member
- 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, property for active property, and list.
- If element has an
9.3 Generate Blank Node Identifier
This algorithm is used to generate new blank node identifiers or to relabel an existing blank node identifier to avoid collision by the introduction of new ones.
General Solution
This section is non-normative.
The simplest case is if there exists already a blank node identifier
in the identifier map for the passed identifier, in which
case it is simply returned. Otherwise, a new blank node identifier
is generated by concatenating the string _:b
and the
counter. If the passed identifier is not null,
an entry is created in the identifier map associating the
identifier with the blank node identifier. Finally,
the counter is increased by one and the new
blank node identifier is returned.
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.
10. RDF Conversion Algorithms
This section describes algorithms to transform 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 | https://www.w3.org/1999/02/22-rdf-syntax-ns# |
rdfs | https://www.w3.org/2000/01/rdf-schema# |
xsd | https://www.w3.org/2001/XMLSchema# |
10.1 Convert to RDF Algorithm
This algorithms converts a JSON-LD document to an RDF dataset.
RDF does not currently allow a blank node identifier to be used as a graph name.
General Solution
This section is non-normative.
The JSON-LD document is expanded and converted to a node map using the
Node Map Generation algorithm.
This allows each graph represented within the document to be
extracted and flattened, making it easier to process each
node object. Each graph from the node map
is processed to extract RDF triples,
to which any (non-default) graph name is applied to create an
RDF dataset. Each node object in the
node map has an @id
member which corresponds to the
RDF subject, the other members
represent RDF predicates. Each
member value is either an IRI or
blank node identifier or can be transformed to an
RDF literal
to generate an RDF triple. Lists
are transformed into an
RDF Collection
using the List to RDF Conversion algorithm.
Algorithm
The algorithm takes a JSON-LD document element and returns an RDF dataset.
- Expand element according the Expansion algorithm.
- Generate a node map according the Node Map Generation algorithm.
- Initialize an empty RDF dataset dataset.
- For each graph name and graph in node map:
- Initialize triples as an empty array.
- For each subject and node in graph:
- For each property and values in node:
- 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, 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 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
- If property is
- For each property and values in node:
- 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.
10.2 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.
General Solution
This section is non-normative.
Value objects are transformed to RDF literals as defined in the section Data Round Tripping whereas node objects are transformed to IRIs or blank node identifiers.
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 ornull
if item does not have such a member. - If value is true or
false, set value to its
canonical lexical form as defined
in the section Data Round Tripping.
If datatype is null, set it to
xsd:boolean
. - Otherwise, if value is a number, then set
value to its canonical lexical form as defined
in the section Data Round Tripping.
If datatype is null, set it to either
xsd:integer
orxsd:double
, depending on if the value contains a fractional and/or an exponential component. - Otherwise, if datatype is null, set it to
xsd:string
orrdf: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 and datatype isrdf:langString
, then add the value associated with the@language
key as the language of literal. - Return literal.
10.3 List to RDF Conversion
List Conversion is the process of taking a list object and transforming it into an RDF Collection as defined in RDF Semantics [RDF-MT].
General Solution
This section is non-normative.
For each element of the list a new blank node identifier
is allocated which is used to generate rdf:first
and
rdf:rest
triples. The
algorithm returns the list head, which is either the the first allocated
blank node identifier or rdf:nil
if the
list is empty.
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.
- Append a triple composed of subject,
- Return the first blank node from bnodes or
rdf:nil
if bnodes is empty.
10.4 Convert from RDF Algorithm
This algorithm converts an RDF dataset consisting of a default graph and zero or more named graphs into a JSON-LD document.
In some cases, data exists natively in the form of triples or triples; for example, if the data was originally represented in an RDF dataset. This algorithm is designed to simply translate an array of triples into a JSON-LD document.
This algorithm does not support lists containing lists.
General Solution
This section is non-normative.
Iterate through each graph in the dataset, converting RDF Collections into a list and generating a JSON-LD document in expanded form for all RDF literals, IRIs and blank node identifiers.
Algorithm
The algorithm takes a single parameter dataset in the form of an array of an RDF dataset.
- Initialize default graph to a new JSON object
consisting of two members,
nodeMap
andlistMap
, whose value is an an empty JSON object. - Initialize graph map to an empty JSON object consisting
of a single member
@default
whose value is set to reference default graph. - Reference the
nodeMap
member of default graph using the variable default graph nodes. - For each graph in 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 a to a new JSON object consisting of two
members,
nodeMap
andlistMap
, whose value is an an empty JSON object. - If graph is not the default graph and
default graph nodes 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 graph object.
- Reference the value of the
nodeMap
member in graph object using the variable node map and the value of thelistMap
member using the variable list map. - For each RDF triple in graph
consisting of subject, predicate, and object:
- If predicate equals
rdf:first
,- If list map has no subject member, create one and initialize it to an empty JSON object.
- Initialize the value of the
first
member of the subject member of list map to the result of the RDF to Object Conversion algorithm, passing object. - Continue with the next RDF triple.
- If predicate equals
rdf:rest
:- If list map has no subject member, create one and initialize it to an empty JSON object.
- Initialize the value of the
rest
member of the subject member of list map to object, which is either an absolute IRI or blank node identifier. - Continue with the next RDF triple.
- 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 predicate equals
rdf:type
, and object is an IRI or blank node identifier, append object to the value of the@type
member of node. 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. - If node does not have an predicate member, create one and initialize its value to an empty array.
- Set value to the result of using the RDF to Object Conversion algorithm, passing object.
- Add a reference to value to the to the array associated with the predicate member of node.
- If object is an IRI or a
blank node identifier it might represent the
head of a RDF list:
- If list map has no object member, create one and set its value to an empty JSON object.
- Set the
head
member of the object member of list map to a reference of value. This reference may be required later to replace the value in the predicate member of node with a list object.
- If predicate equals
- If graph is the default graph,
set name to
- For each name and graph object in graph map:
- Reference the value of the
listMap
member in graph object using the variable list map. - For each key-value pair subject-entry of the
value associated to the
listMap
member of graph object:- If entry has not an
head
and anfirst
member it does not represent the head of a list. Continue with the next key-value pair. - Reference the value of the
head
member in entry using the variable value. - Remove the
@id
member from value. - Add an
@list
member to value and initialize it to an array containing the value of thefirst
member of entry. - While the value associated with the
rest
member of entry is notrdf:nil
:- Set rest to the value of the
rest
member of entry. - Set entry to the value associated with the rest member of list map.
- Add the value associated with the
first
member of entry to the@list
member of value.
- Set rest to the value of the
- If entry has not an
- Reference the value of the
- Initialize an empty array result.
- For each subject and node in default graph nodes
ordered by subject:
- If graph map has an subject member:
- Add a
@graph
member to node and initialize its value to an empty array. - Reference the
nodeMap
member of the subject member of graph map using the variable node map. - For each key-value pair s-n in node map
ordered by s, append n to the
@graph
member of node.
- Add a
- Append node to result.
- If graph map has an subject member:
- Return result.
10.5 RDF to Object Conversion
This algorithm transforms an RDF literal to a JSON-LD value object and a RDF blank node or IRI to an JSON-LD node object.
General Solution
This section is non-normative.
RDF literals are transformed to value objects as defined in the section Data Round Tripping whereas IRIs and blank node identifiers are transformed to node objects.
Algorithm
This algorithm takes as single input variable value that is converted to a JSON object.
- If value is an an IRI or a
blank node identifier:
- If value equals
rdf:nil
return a new JSON object consisting of a single member@list
whose value is set to an empty array. This is behavior is required by the Convert from RDF algorithm. - Otherwise, return a new JSON object consisting of
a single member
@id
whose value is set to value.
- If value equals
- Otherwise value is an
RDF literal:
- Initialize a new empty JSON object result.
- Initialize converted value to value.
- Initialize type to null
- If the
datatype IRI
of value equals
xsd:boolean
, set converted value to true if the lexical form of value matchestrue
, orfalse
if it matchesfalse
. - Otherwise, if the
datatype IRI
of value equals
xsd:integer
orxsd:double
, try to convert the literal to a JSON number. If the conversion is successful, store the result in converted value. - 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.
10.6 Data Round Tripping
When converting JSON-LD to RDF JSON-native types such as
numbers and booleans are automatically coerced to
xsd:integer
, xsd:double
, or xsd:boolean
.
Implementers MUST ensure that the result is in canonical lexical form. A
canonical lexical form is a set of literals from among the valid set of literals for
a datatype such that there is a one-to-one mapping between the canonical lexical form
and a value in the value space as defined in [XMLSCHEMA11-2]. In other words, every
value MUST be converted to a deterministic string representation.
The canonical lexical form of an integer, i.e., a number without fractions
or a number coerced to xsd:integer
, is a finite-length sequence of decimal
digits (0-9
) with an optional leading minus sign; leading zeros are prohibited.
To convert the number in JavaScript, implementers can use the following snippet of code:
(value).toFixed(0).toString()
The canonical lexical form of a double, i.e., a number with fractions
or a number coerced to xsd:double
, consists of a mantissa followed by the
character "E", followed by an exponent. The mantissa MUST be a decimal number. The exponent
MUST be an integer. Leading zeros and a preceding plus sign (+
) are prohibited
in the exponent. If the exponent is zero, it must be indicated by E0
.
For the mantissa, the preceding optional plus sign is prohibited and the decimal point is
required. Leading and trailing 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]; in JSON-LD the mantissa is rounded to 15 digits after the
decimal point.
To convert the number in JavaScript, implementers can use the following snippet of code:
(value).toExponential(15).replace(/(\d)0*e\+?/,'$1E')
When data such as decimals need to be normalized, JSON-LD authors should
not use values that are going to undergo automatic conversion. This is due to the lossy nature
of xsd:double
values. Authors should instead use the expanded object form to
set the canonical lexical form directly.
The canonical lexical form of the boolean values true and false
are the strings true
and false
.
When JSON-native numbers, are type coerced, lossless data round-tripping can not
be guaranteed as rounding errors might occur. Additionally, only literals typed as
xsd:integer
, xsd:double
, and xsd:boolean
are
automatically converted back to their JSON-native counterparts in when
converting from RDF.
Some JSON serializers, such as PHP's native implementation in some versions,
backslash-escape the forward slash character. For example, the value
https://example.com/
would be serialized as http:\/\/example.com\/
.
This is problematic as other JSON parsers might not understand those escaping characters.
There is no need to backslash-escape forward slashes in JSON-LD. To aid interoperability
between JSON-LD processors, a JSON-LD serializer MUST NOT backslash-escape forward slashes.
11. The Application Programming Interface
This API provides a clean mechanism that enables developers to convert JSON-LD data into a a variety of output formats that are often easier to work with. A conformant JSON-LD Processor MUST implement the entirety of the following API.
11.1 JsonLdProcessor
The JSON-LD Processor 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 processors MUST NOT modify
the input parameters. If an error is detected, the callback is
invoked passing a JsonLdError
with the corresponding error
code
and processing is stopped.
[Constructor]
interface JsonLdProcessor {
void expand ((object or object[] or DOMString) input, JsonLdCallback
callback, optional JsonLdOptions
? options);
void compact ((object or object[] or DOMString) input, (object or DOMString)? context, JsonLdCallback
callback, optional JsonLdOptions
? options);
void flatten ((object or object[] or DOMString) input, (object or DOMString)? context, JsonLdCallback
callback, optional JsonLdOptions
? options);
};
Methods
compact
-
Compacts the given
input
using thecontext
according to the steps in the Compaction algorithm:- If the passed input is a DOMString representing the IRI
of a remote document, dereference it. If the retrieved document has a content type
different than
application/ld+json
orapplication/json
or if the document cannot be parsed as JSON, invoke the callback passing anloading document failed
error. - Initialize a new empty active context.
- If an
expandContext
has been passed, update the active context using the Context Processing algorithm, passing theexpandContext
as local context. - If the input has been retrieved and the response has a content type
application/json
and an HTTP Link Header [RFC5988] using thehttps://www.w3.org/ns/json-ld#context
link relation, update the active context using the Context Processing algorithm, passing the context referenced in the HTTP Link Header as local context. - 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. - Invoke callback, passing null for error and compacted for document.
Parameter Type Nullable Optional Description input (object or object[] or DOMString)
✘ ✘ The JSON-LD object or array of JSON-LD objects to perform the compaction upon or an IRI referencing the JSON-LD document to compact. context (object or DOMString)
✔ ✘ The context to use when compacting the input
; either in the form of a JSON object or as IRI.callback JsonLdCallback
✘ ✘ A callback that is called when processing completed successfully on the given input
, or a fatal error prevented processing from completing.options JsonLdOptions
✔ ✔ A set of options to configure the algorithms. This allows, e.g., to set the input document's base IRI. Return type:void
- If the passed input is a DOMString representing the IRI
of a remote document, dereference it. If the retrieved document has a content type
different than
expand
-
Expands the given
input
according to the steps in the Expansion algorithm:- If the passed input is a DOMString representing the IRI
of a remote document, dereference it. If the retrieved document has a content type
different than
application/ld+json
orapplication/json
or if the document cannot be parsed as JSON, invoke the callback passing anloading document failed
error. - Initialize a new empty active context.
- If an
expandContext
has been passed, update the active context using the Context Processing algorithm, passing theexpandContext
as local context. - If the input has been retrieved and the response has a content type
application/json
and an HTTP Link Header [RFC5988] using thehttps://www.w3.org/ns/json-ld#context
link relation, update the active context using the Context Processing algorithm, passing the context referenced in the HTTP Link Header as local context. - Set expanded to the result of using the Expansion algorithm, passing the active context and input as element.
- Invoke callback, passing null for error and expanded for document.
Parameter Type Nullable Optional Description input (object or object[] or DOMString)
✘ ✘ The JSON-LD object or array of JSON-LD objects to perform the expansion upon or an IRI referencing the JSON-LD document to expand. callback JsonLdCallback
✘ ✘ A callback that is called when processing completed successfully on the given input
, or a fatal error prevented processing from completing.options JsonLdOptions
✔ ✔ A set of options to configure the used algorithms such. This allows, e.g., to set the input document's base IRI. Return type:void
- If the passed input is a DOMString representing the IRI
of a remote document, dereference it. If the retrieved document has a content type
different than
flatten
-
Flattens the given
input
and compacts it using the passedcontext
according to the steps in the Flattening algorithm:- If the passed input is a DOMString representing the IRI
of a remote document, dereference it. If the retrieved document has a content type
different than
application/ld+json
orapplication/json
or if the document cannot be parsed as JSON, invoke the callback passing anloading document failed
error. - Initialize a new empty active context.
- If an
expandContext
has been passed, update the active context using the Context Processing algorithm, passing theexpandContext
as local context. - If the input has been retrieved and the response has a content type
application/json
and an HTTP Link Header [RFC5988] using thehttps://www.w3.org/ns/json-ld#context
link relation, update the active context using the Context Processing algorithm, passing the context referenced in the HTTP Link Header as local context. - 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). - Invoke callback, passing null for error and flattened for document.
Parameter Type Nullable Optional Description input (object or object[] or DOMString)
✘ ✘ The JSON-LD object or array of JSON-LD objects or an IRI referencing the JSON-LD document to flatten. context (object or DOMString)
✔ ✘ The context to use when compacting the flattened input
; either in the form of a JSON object or as IRI. If null is passed, the result will not be compacted but kept in expanded form.callback JsonLdCallback
✘ ✘ A callback that is called when processing completed successfully on the given input
, or a fatal error prevented processing from completing.options JsonLdOptions
✔ ✔ A set of options to configure the used algorithms such. This allows, e.g., to set the input document's base IRI. Return type:void
- If the passed input is a DOMString representing the IRI
of a remote document, dereference it. If the retrieved document has a content type
different than
11.2 Callbacks
JSON-LD processors utilize callbacks in order to exchange information in an asynchronous manner with applications. This section details the parameters of those callbacks.
JsonLdCallback
The JsonLdCallback
is called when an API method of
JsonLdProcessor
has been completed, either successfully or
by a fatal error.
callback JsonLdCallback = void (JsonLdError
error, object or object[] document);
Callback JsonLdCallback
Parameters
error
of typeJsonLdError
- If the value is null, then no issue was detected during processing. Otherwise, a processing error was detected and the details are contained within the error object.
document
of type array of object or object- The processed JSON-LD document.
LoadContextCallback
The LoadContextCallback
defines the callback that custom context loaders
have to implement to be used to retrieve remote contexts.
callback LoadContextCallback = void (DOMString url, ContextLoadedCallback
callback);
Callback LoadContextCallback
Parameters
url
of type DOMString- The URL of the remote context to load.
callback
of typeContextLoadedCallback
- The callback that is called when the remote context has been successfully loaded or an error preventing its loading has been detected.
ContextLoadedCallback
The ContextLoadedCallback
is called in response to a call
of the LoadContextCallback
.
callback ContextLoadedCallback = void (JsonLdError
error, DOMString url, DOMString context);
Callback ContextLoadedCallback
Parameters
error
of typeJsonLdError
- If the value is null, then no issue was detected
during processing. Otherwise, a processing issue was detected and
the details are contained within the error object. All
errors MUST have a
JsonLdErrorCode
ofloading remote context failed
. url
of type DOMString- The final URL of the loaded JSON-LD context. This is important to handle HTTP redirects properly.
context
of type DOMString- The raw content of the retrieved JSON-LD context.
11.3 Data Structures
This section describes datatype definitions used within the JSON-LD API.
JsonLdOptions
The JsonLdOptions
type is used to pass various options to the
JsonLdProcessor
methods.
dictionary JsonLdOptions {
DOMString base;
boolean compactArrays = true;
LoadContextCallback
loadContext;
object or DOMString expandContext = null;
DOMString processingMode = "json-ld-1.0";
};
Dictionary JsonLdOptions
Members
base
of type DOMString- The Base IRI to use when expanding or compacting the document. This overrides the value of
input if it is a IRI. If not specified and input is not
an IRI, the base IRI defaults to the current document IRI if in a browser context,
or the empty string if there is no document context.
Issue 223: Feature at risk
The default value of this option implies that all IRIs that cannot be compacted otherwise are transformed to relative IRIs during compaction. To avoid that data is being lost, developers thus have to store the base IRI along with the compacted document. This might be problematic in practice and thus the default behavior might be changed in future. Furthermore, the relationship of this option to the
@base
keyword (which is at risk) should be further investigated. compactArrays
of type boolean, defaulting totrue
- If set to
true
, the JSON-LD processor replaces arrays with just one element with that element during compaction. If set tofalse
, all arrays will remain arrays even if they have just one element. expandContext
of type object or DOMString, defaulting tonull
- A context that is used to initialize the active context when expanding a document.
loadContext
of typeLoadContextCallback
- The callback of the context loader to be used to retrieve remote contexts. If specified, it MUST be used to retrieve remote contexts; otherwise, if not specified, the processor's built-in context loader MUST be used.
processingMode
of type DOMString, defaulting to"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 withjson-ld
as they are reserved for future versions of this specification.
JsonLdError
The JsonLdError
type is used to report processing errors
to a JsonLdCallback
.
dictionary JsonLdError {
JsonLdErrorCode
code;
DOMString? message;
};
Dictionary JsonLdError
Members
code
of typeJsonLdErrorCode
- a string representing the particular error type, as described in the various algorithms in this document.
message
of type DOMString, nullable- 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.
enum JsonLdErrorCode {
"loading document failed",
"list of lists",
"invalid @index value",
"conflicting indexes",
"invalid @id value",
"invalid local context",
"loading remote context failed",
"invalid remote context",
"recursive context inclusion",
"invalid base IRI",
"invalid vocab mapping",
"invalid default language",
"keyword redefinition",
"invalid term definition",
"invalid reverse property",
"invalid IRI mapping",
"cyclic IRI mapping",
"invalid keyword alias",
"invalid type mapping",
"invalid language mapping",
"colliding keywords",
"invalid container mapping",
"invalid type value",
"invalid value object",
"invalid value object value",
"invalid language-tagged string",
"invalid language-tagged value",
"invalid typed value",
"invalid set or list object",
"invalid language map value",
"compaction to list of lists",
"invalid reverse property map",
"invalid @reverse value",
"invalid reverse property value"
};
Enumeration description | |
---|---|
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 conversion 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. |
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. |
A. Acknowledgements
This section is non-normative.
A large amount of thanks goes out to the JSON-LD Community Group participants who worked through many of the technical issues on the mailing list and the weekly telecons - of special mention are Niklas Lindström, François Daoust, Lin Clark, and Zdenko 'Denny' Vrandečić. The editors would like to thank Mark Birbeck, who provided a great deal of the initial push behind the JSON-LD work via his work on RDFj. The work of Dave Lehn and Mike Johnson are appreciated for reviewing, and performing several implementations of the specification. Ian Davis is thanked for his work on RDF/JSON. Thanks also to Nathan Rixham, Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant, Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Josh Mandel, Eric Prud'hommeaux, David Wood, Guus Schreiber, Pat Hayes, Sandro Hawke, and Richard Cyganiak or their input on the specification.
B. References
B.1 Normative references
- [IEEE-754-1985]
- IEEE. IEEE Standard for Binary Floating-Point Arithmetic. URL: https://standards.ieee.org/reading/ieee/std_public/description/busarch/754-1985_desc.html
- [JSON-LD]
- Manu Sporny, Gregg Kellogg, Markus Lanthaler, Editors. JSON-LD 1.0. W3C Editor's Draft (work in progress). URL: https://json-ld.org/spec/latest/json-ld-syntax/
- [RDF-MT]
- Patrick Hayes. RDF Semantics. 10 February 2004. W3C Recommendation. URL: https://www.w3.org/TR/2004/REC-rdf-mt-20040210
- [RFC2119]
- S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Internet RFC 2119. URL: https://www.ietf.org/rfc/rfc2119.txt
- [RFC3986]
- T. Berners-Lee; R. Fielding; L. Masinter. Uniform Resource Identifier (URI): Generic Syntax. January 2005. RFC 3986. URL: https://www.ietf.org/rfc/rfc3986.txt
- [RFC3987]
- M. Dürst; M. Suignard. Internationalized Resource Identifiers (IRIs). January 2005. RFC 3987. URL: https://www.ietf.org/rfc/rfc3987.txt
- [RFC4627]
- D. Crockford. The application/json Media Type for JavaScript Object Notation (JSON). July 2006. RFC 4627. URL: https://www.ietf.org/rfc/rfc4627.txt
- [RFC5988]
- M. Nottingham. Web Linking. October 2010. Internet RFC 5988. URL: https://www.ietf.org/rfc/rfc5988.txt
- [WEBIDL]
- Cameron McCormack, Editor. Web IDL. 19 April 2012. W3C Candidate Recommendation (work in progress). URL: https://www.w3.org/TR/2012/CR-WebIDL-20120419/. The latest edition is available at https://www.w3.org/TR/WebIDL/
- [XMLSCHEMA11-2]
- Henry S. Thompson et al. W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes. 5 April 2012. W3C Recommendation. URL: https://www.w3.org/TR/2012/REC-xmlschema11-2-20120405/
B.2 Informative references
- [BCP47]
- A. Phillips; M. Davis. Tags for Identifying Languages. September 2009. IETF Best Current Practice. URL: https://tools.ietf.org/html/bcp47
- [ECMA-262]
- ECMAScript Language Specification. June 2011. URL: https://www.ecma-international.org/publications/standards/Ecma-262.htm
- [JSON-LD-TESTS]
- JSON-LD Test Suite (work in progress).
- [RDF11-CONCEPTS]
- Richard Cyganiak, David Wood, Editors. RDF 1.1 Concepts and Abstract Syntax. 15 January 2013. W3C Working Draft (work in progress). URL: https://www.w3.org/TR/2013/WD-rdf11-concepts-20130115/. The latest edition is available at https://www.w3.org/TR/rdf11-concepts/
- [TURTLE]
- Eric Prud'hommeaux, Gavin Carothers, Editors. Turtle: Terse RDF Triple Language. 19 February 2013. W3C Candidate Recommendation (work in progress). URL: https://www.w3.org/TR/2013/CR-turtle-20130219/. The latest edition is available at https://www.w3.org/TR/turtle/