This document is also available in this non-normative format: diff to previous version.
This document is licensed under a Creative Commons Attribution 3.0 License.
JSON [RFC4627] has proven to be a highly useful object serialization and messaging format. JSON-LD [JSON-LD] harmonizes the representation of Linked Data in JSON by outlining a common JSON representation format for expressing directed graphs; mixing both Linked Data and non-Linked Data in a single document. This document outlines an Application Programming Interface and a set of algorithms for programmatically transforming JSON-LD documents.
This document is merely a public working draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organisation.
This document is an experimental work in progress.
JSON, as specified in [RFC4627], is a simple language for representing data on the Web. Linked Data is a technique for creating a graph of interlinked data across different documents or Web sites. Data entities are described using IRIs, which are typically dereferencable and thus may be used to find more information about an entity, creating a "Web of Knowledge". JSON-LD is intended to be a simple publishing method for expressing not only Linked Data in JSON, but also for adding semantics to existing JSON.
JSON-LD is designed as a light-weight syntax that can be used to express Linked Data. It is primarily intended to be a way to use Linked Data in Javascript and other Web-based programming environments. It is also useful when building interoperable Web services and when storing Linked Data in JSON-based document storage engines. It is practical and designed to be as simple as possible, utilizing the large number of JSON parsers and libraries available today. It is designed to be able to express key-value pairs, RDF data, RDFa [RDFA-CORE] data, Microformats [MICROFORMATS] data, and Microdata [MICRODATA]. That is, it supports every major Web-based structured data model in use today.
The syntax does not necessarily require applications to change their JSON, but allows to easily add meaning by adding context in a way that is either in-band or out-of-band. The syntax is designed to not disturb already deployed systems running on JSON, but provide a smooth upgrade path from JSON to JSON with added semantics. Finally, the format is intended to be easy to parse, efficient to generate, convertible to RDF in one pass, and require a very small memory footprint in order to operate.
This document is a detailed specification for a serialization of Linked Data in JSON. The document is primarily intended for the following audiences:
To understand the basics in this specification you must first be familiar with JSON, which is detailed in [RFC4627]. You must also understand the JSON-LD Syntax [JSON-LD], which is the base syntax used by all of the algorithms in this document. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ECMA-262] and WebIDL [WEBIDL]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [RDF-CONCEPTS].
Examples may contain references to existing vocabularies and use prefixes to refer to vocabularies. The following is a list of all vocabularies and their prefix abbreviations, as used in this document:
dc
, e.g., dc:title
)foaf
, e.g., foaf:knows
)rdf
, e.g., rdf:type
)xsd
, e.g., xsd:integer
)JSON [RFC4627] defines several terms which are used throughout this document:
@value
, @list
or @set
and it has one or more keys other than @id
.@id
key.The following definition for Linked Data is the one that will be used for this specification.
Note that the definition for Linked Data above is silent on the topic of unlabeled nodes. Unlabeled nodes are not considered Linked Data. However, this specification allows for the expression of unlabled nodes, as most graph-based data sets on the Web contain a number of associated nodes that are not named and thus are not directly de-referenceable.
There are a number of ways that one may participate in the development of this specification:
This API provides a clean mechanism that enables developers to convert JSON-LD data into a a variety of output formats that are easier to work with in various programming languages. If a JSON-LD API is provided in a programming environment, the entirety of the following API must be implemented.
[NoInterfaceObject]
interface JsonLdProcessor {
void expand (object or object[] or URL input, JsonLdCallback
callback, optional JsonLdOptions
options);
void compact (object or object[] or URL input, object or URL context, JsonLdCallback
callback, optional JsonLdOptions
options);
void frame (object or object[] or URL input, object or URL frame, JsonLdCallback
callback, optional JsonLdOptions
options);
void fromRDF (Statement
[] input, JsonLdCallback
callback, optional JsonLdOptions
options);
void toRDF (object or object[] or URL input, ObjectOrURL? context, StatementCallback
callback, optional JsonLdOptions
options);
};
compact
input
using the
context
according to the steps in the
Compaction Algorithm. The
input
must be copied, compacted and returned if there are
no errors. If the compaction fails, an appropirate exception must be
thrown.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input | object or object[] or URL | ✘ | ✘ | 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 URL | ✘ | ✘ | The context to use when compacting the input ; either in the
form of an JSON object or as IRI. |
callback |
| ✘ | ✘ | A callback that is called when processing is complete on
the given input . |
options |
| ✘ | ✔ | A set of options that may affect the expansion algorithm such as, e.g., the
input document's base IRI. This also includes optimize ,
which if set will cause processor-specific optimization. |
void
expand
input
according to
the steps in the Expansion Algorithm. The
input
must be copied, expanded and returned if there are
no errors. If the expansion fails, an appropriate exception must be thrown.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input | object or object[] or URL | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects to perform the expansion upon or an IRI referencing the JSON-LD document to expand. |
callback |
| ✘ | ✘ | A callback that is called when processing is complete on
the given input . |
options |
| ✘ | ✔ | A set of options that may affect the expansion algorithm such as, e.g., the input document's base IRI. |
void
frame
input
using the
frame
according to the steps in the
Framing Algorithm. The input
is used to build the framed output and is returned if there are no errors.
If there are no matches for the frame, null must be
returned. Exceptions must be thrown if there are errors.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input | object or object[] or URL | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects to perform the framing upon or an IRI referencing the JSON-LD document to frame. |
frame | object or URL | ✘ | ✘ | The frame to use when re-arranging the data of input ; either
in the form of an JSON object or as IRI. |
callback |
| ✘ | ✘ | A callback that is called when processing is complete on
the given input . |
options |
| ✘ | ✔ | A set of options that may affect the framing algorithm such as, e.g., the input document's base IRI. |
void
fromRDF
Statement
s.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
| ✘ | ✘ | An array of RDF statements. |
callback |
| ✘ | ✘ | A callback that is called when processing is complete on
the given input . |
options |
| ✘ | ✔ | A set of options that will affect the algorithm. This includes notType ,
which if set to true causes the resulting document to use rdf:type
as a property, instead of @type . |
void
toRDF
input
according to the
Convert to RDF Algorithm, calling
the provided callback
for each Statement
generated.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input | object or object[] or URL | ✘ | ✘ | The JSON-LD object or array of JSON-LD objects to convert to RDF or an IRI referencing the JSON-LD document to convert to RDF. |
context | ObjectOrURL | ✔ | ✘ | An external context to use additionally to the context embedded in
input when expanding the input . |
callback |
| ✘ | ✘ | A callback that is called when a Statement is created from processing
the given input . |
options |
| ✘ | ✔ | A set of options that may affect the conversion to RDF such as, e.g., the input document's base IRI. |
void
The JsonLdCallback
is used to return a processed JSON-LD representation
as the result of processing an API method.
[NoInterfaceObject Callback]
interface JsonLdCallback {
void jsonLd (ObjectOrObjectArray jsonld);
};
jsonLd
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
jsonld | ObjectOrObjectArray | ✘ | ✘ | The processed JSON-LD document. |
void
The StatementCallback
is called whenever the processor generates a
statement during the statement()
call.
[NoInterfaceObject Callback]
interface StatementCallback {
void statement (Statement
statement);
};
This section describes datatype definitions used within the JSON-LD API.
The URL
datatype is a string representation of an IRI.
typedef DOMString URL;
JSON object
or array
.
The JsonLdOptiones type is used to convery a set of options to an interface method.
typedef object JsonLdOptions;
URL
baseURL
or if it is a object
or object[]
.true
, the JSON-LD processor is allowed to
optimize the output of the Compaction Algorithm
to produce even compacter representations. The algorithm for compaction
optimization is beyond the scope of this specification and thus
not defined. Consequently, different implementations may implement
different optimization algorithms.true
, the JSON-LD processor will not use the
@type
property when generating the output, and will use the
expanded rdf:type
IRI as the property instead of @type
.The following data structures are used for representing data about RDF statements (triples or quads). They are used for normalization, fromRDF, and from toRDF interfaces.
The Statement
interface represents an RDF Statement.
[NoInterfaceObject]
interface Statement {
readonly attribute Node
subject;
readonly attribute Node
property;
readonly attribute Node
object;
readonly attribute Node
? name;
};
name
of type Node
, readonly, nullableStatement
identifying
it as a member of a named graph. If the attribute is present,
it indicates that this statement is a member of a named graph
associated with name. If it is missing, the statement
is a member of the default graph.object
of type Node
, readonlyStatement
.property
of type Node
, readonlyStatement
.subject
of type Node
, readonlyStatement
.Node
is the base class of NamedNode
,
BlankNode
, and LiteralNode
.
[NoInterfaceObject]
interface Node {
readonly attribute DOMString nominalValue;
readonly attribute DOMString interfaceName;
};
interfaceName
of type DOMString, readonlyProvides access to the string name of the current interface,
normally one of "IRI"
, "BlankNode"
or "LiteralNode"
.
This method serves to disambiguate instances of Node
which
are otherwise identical, such as NamedNode
and BlankNode
.
nominalValue
of type DOMString, readonlyThe nominalValue
of an Node
is refined by
each interface which extends Node
.
A node identified by an IRI. NamedNodes are defined by International Resource Identifier [IRI].
[NoInterfaceObject]
interface NamedNode : Node
{
readonly attribute DOMString nominalValue;
};
nominalValue
of type DOMString, readonlyA BlankNode
is a reference to an unnamed resource
(one for which an IRI is not known), and may be used in a Statement
as a unique reference to that unnamed resource.
[NoInterfaceObject]
interface BlankNode : Node
{
readonly attribute DOMString nominalValue;
};
Developers and authors must not assume that the
nominalValue of a BlankNode
will remain the same between two
processing runs. BlankNode
nominalValues are only valid for the
most recent processing run on the document. BlankNode
s
nominalValues will often be generated differently by different processors.
Implementers must ensure that BlankNode
nominalValues are unique
within the current environment, two BlankNode
s are considered equal if, and only if,
their nominalValues are strictly equal.
LiteralNodes represent values such as numbers, dates and strings in
RDF data. A LiteralNode
is comprised of three attributes:
nominalValue
language
represented by a string tokendatatype
specified by a NamedNode
LiteralNodes representing plain text in a natural language may have a
language
attribute specified by a text string token, as specified in
[BCP47], normalized to lowercase
(e.g., 'en'
, 'fr'
, 'en-gb'
).
They may also have a datatype attribute such as xsd:string
.
LiteralNodes representing values with a specific datatype, such as
the integer 72, may have a datatype
attribute specified in the form
of a NamedNode
(e.g.,
<http://www.w3.org/2001/XMLSchema#integer>
).
[NoInterfaceObject]
interface LiteralNode : Node
{
readonly attribute DOMString nominalValue;
readonly attribute DOMString? language;
readonly attribute NamedNode
? datatype;
};
datatype
of type NamedNode
, readonly, nullablelanguage
of type DOMString, readonly, nullablenominalValue
of type DOMString, readonlyAll algorithms described in this section are intended to operate on language-native data structures. That is, the serialization to a text-based JSON document isn't required as input or output to any of these algorithms and language-native data structures must be used where applicable.
JSON-LD specifies a number of syntax tokens and keywords that are using in all algorithms described in this section:
@context
@id
@language
@type
@value
@container
@list
@set
@graph
:
@default
@explicit
@omitDefault
@embed
@null
All JSON-LD tokens and keywords are case-sensitive.
@context
keyword.
Processing of JSON-LD data structure is managed recursively. During processing, each rule is applied using information provided by the active context. Processing begins by pushing a new processor state onto the processor state stack and initializing the active context with the initial context. If a local context is encountered, information from the local context is merged into the active context.
The active context is used for expanding properties and values of a JSON object (or elements of a list (see List Processing)) using a term mapping. It is also used to maintain coercion mappings from terms to datatypes, language mappings from terms to language codes, and list mappings and set mappings for terms. Processors must use the lexical form of the property when creating a mapping, as lookup is performed on lexical representations, not expanded IRI representations.
A local context is identified within a JSON object having a @context
property with a string, array or a JSON object value.
When processing a local context, special processing rules apply:
@context
@context
element using the JSON Pointer "/@context" as described in [JSON-POINTER]. Set context
to the extracted content and process it by starting at Step 2.1.@language
property, it must have a value of a
simple string or null. Add the language to the local context.@id
, @language
or @type
properties, throw an exception.
@type
or @graph
can take a
@container
with @set
.
@id
property with a string value which must have the form of a term,
compact IRI, or absolute IRI. Determine the IRI mapping
by performing IRI Expansion on the associated value.
If the result of the IRI mapping is an absolute IRI, merge the
property into the local context term mapping.@id
property with a string value which must have the
form of a term, compact IRI, or absolute IRI.
Determine the IRI mapping by performing IRI Expansion on the associated
value. If the result of the IRI mapping is an absolute IRI, merge the
property into the local context term mapping.@type
property, it's value must have the form of a term,
compact IRI, absolute IRI, or the keyword @id
.
Determine the IRI by performing IRI Expansion on the associated value.
If the result of the IRI mapping is an absolute IRI or @id
, merge into the
local context coercion mapping using the lexical value of the property.@container
property, it's value must be @list
or
@set
. Merge the list mapping or set mapping into the
local context using the lexical value of the property.@language
property but no @type
property, the value of the
@language
property must be a string or null.
Merge the language mapping into the local context using the lexical value of the
property.It can be difficult to distinguish between a compact IRI and an absolute IRI, as a compact IRI may seem to be a valid IRI scheme. When performing repeated IRI expansion, a term used as a prefix may not have a valid mapping due to dependencies in resolving term definitions. By continuing Step 2.3.2 until no changes are made, mappings to IRIs created using an undefined term prefix will eventually resolve to absolute IRIs.
Issue 43 concerns performing IRI expansion in the key position of a context definition.
Keys and some values are evaluated to produce an IRI. This section defines an algorithm for transforming a value representing an IRI into an actual IRI.
IRIs may be represented as an absolute IRI, a term or a compact IRI.
An absolute IRI is defined in [RFC3987] containing a scheme along with path and optional query and fragment segments. 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.
The algorithm for generating an IRI is:
Previous versions of this specification used @base
and @vocab
to define IRI prefixes
used to resolve relative IRIs. It was determined that this added too much complexity, but the issue
can be re-examined in the future based on community input.
Some keys and values are expressed using IRIs. This section defines an algorithm for transforming an IRI (iri) to a term or compact IRI using the terms specified in the active context using an optional value.
The algorithm for generating a compact IRI is:
0
,
and set a flag list container to false
.@list
:
@container
set to @set
, continue
to the next term.true
and term does not have a
container
set to @list
, continue to the next term.container
set to @list
,
continue to the next term.0
:
container
set to @set
, then add
1
to rank.@list
and list container is false
and term has a container
set to @list
, then set list container to true
, clear
terms, set highest rank to rank, and add term to terms.When selecting among multiple possible terms for a given property, it may be that multiple
terms are defined with the same IRI, but differ in @type
, @container
or @language
. The purpose of this algorithm is to take an term
and a value and give it a term rank. The selection can then be based, partly, on
the term having the highest term rank.
Given a term term, value, and active context determine the term rank using the following steps:
3
.@list
:
@type
coercion to xsd:boolean
,
xsd:integer
, or xsd:double
respectively,
term rank is 3
, otherwise if term has no @type
or
@language
it is 2
, otherwise 1
.@language
. If term has @language
null,
or term has no @type
or @language
and the active context
has no @language
, term rank is 3
, otherwise 0
.@value
.
@value
property, it must have either a @type
or a @language
:
@type
property matching a
@type
coercion for term, term rank
is 3
, otherwise if term has no @type
coersion and no @language
, term rank is
1
, otherwise 0
.@language
property matching a
@language
definition for term (or
term has no @type
or @language
definition and
@language
in the active context matches the
value @language
), term rank is
3
, otherwise if term has no @type
coersion and no @language
, term rank is
1
, otherwise 0
.@type
coerced to @id
,
term rank is 3
, otherwise
if term has no @type
coersion and no @language
,
term rank is 1
, otherwise 0
.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.
The algorithm for expanding a value takes an active property and active context. It is implemented as follows:
xsd:integer
or xsd:double
, expand the value into an object with
two key-value pairs. The first key-value pair will be @value
and the string representation of
value as defined in the section Data Round Tripping. The second
key-value pair will be @type
and the associated coercion datatype expanded according to the
IRI Expansion rules.@graph
, or the target of an @id
coercion, expand the value
into an object with a key-value pair where the key is @id
and the value is the expanded
IRI according to the IRI Expansion rules.@value
and the unexpanded value. The second key-value pair will be @type
and the associated coercion
datatype expanded according to the IRI Expansion rules.@value
and the unexpanded value.
The second key-value pair will be @language
and value of the language tagging from the active context.Some values, such as IRIs and typed literals, may be expressed in an expanded form in JSON-LD. These values are required to be compacted at times when processing JSON-LD documents.
The algorithm for compacting an expanded value value takes an active property and active context. It is implemented as follows:
@value
value.@graph
, the compacted value is the
value associated with the @id
key, processed according to
the IRI Compaction steps.@id
, the compacted
value is the value associated with the @id
key,
processed according to the
IRI Compaction steps.@value
key.@id
key, the compacted value is value with
the value of @id
processed according to the
IRI Compaction steps.@language
, which
matches the @language
of the value, or the value has only a @value
key, the compacted
value is the value associated with the @value
key.@type
key, the compacted value
is value with the @type
value processed according to the
IRI Compaction steps.This algorithm is used by the Framing Algorithm and Convert From RDF Algorithm to deterministicly name blank node identifiers. It uses a identifier map and prefix and takes a possibly null identifier and returns a new identifier based on prefix.
The variable next identifier is initialized to prefix appended with 0
.
Expansion is the process of taking a JSON-LD document and applying a context such that all IRI, datatypes, and literal values are expanded so that the context is no longer necessary. JSON-LD document expansion is typically used as a part of Framing.
For example, assume the following JSON-LD input document:
{ "@context": { "name": "http://xmlns.com/foaf/0.1/name", "homepage": { "@id": "http://xmlns.com/foaf/0.1/homepage", "@type", "@id" } }, "name": "Manu Sporny", "homepage": "http://manu.sporny.org/" }
Running the JSON-LD Expansion algorithm against the JSON-LD input document provided above would result in the following output:
{ "http://xmlns.com/foaf/0.1/name": "Manu Sporny", "http://xmlns.com/foaf/0.1/homepage": { "@id": "http://manu.sporny.org/" } }
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 initial context, active property is set to null, and element is set to the JSON-LD input.
@container
set to @list
and any entry in element is an
array, or is a JSON object containing a @list
property,
throw an exception, as lists of lists are not allowed.
If the expanded entry is null, drop it. If it's an array, merge it's entries with element's entries.@context
property, update the active context according to
the steps outlined in Context Processing and remove the @context
property.@value
, continue with the next
property from element.@id
the value must be a string.
Expand the value according to IRI Expansion.@type
:
@id
.@value
or @language
the value must not be a
JSON object or an array.@list
, @set
, or @graph
, expand value
recursively using this algorithm, passing copies of the active context and active property. If the expanded
value is not an array, convert it to an array.
If property is @list
and any entry in value is a
JSON object containing an @list
property, throw an exception, as
lists of lists are not supported.@container
@list
and the expanded value is not null,
convert value to an object with an @list
property whose value is
set to value (unless value is already in that form).@id
, @type
, @value
, or @language
.@value
property
@type
property and it's value is not in the form of an
array, convert it to an array.@set
or @list
property, it must be the only property.
Set element to the value of @set
; leave @list
untouched.@language
property, set element to null.If, after the algorithm outlined above is run, the resulting element is an JSON object with just a @graph
property, element is set to the value of @graph
's value. Finally, if element is a JSON object,
it is wrapped into an array.
Compaction is the process of taking a JSON-LD document and applying a context such that the most compact form of the document is generated. JSON is typically expressed in a very compact, key-value format. That is, full IRIs are rarely used as keys. At times, a JSON-LD document may be received that is not in its most compact form. JSON-LD, via the API, provides a way to compact a JSON-LD document.
For example, assume the following JSON-LD input document:
{ "http://xmlns.com/foaf/0.1/name": "Manu Sporny", "http://xmlns.com/foaf/0.1/homepage": { "@id": "http://manu.sporny.org/" } }
Additionally, assume the following developer-supplied JSON-LD context:
{ "@context": { "name": "http://xmlns.com/foaf/0.1/name", "homepage": { "@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id" } } }
Running the JSON-LD Compaction algorithm given the context supplied above against the JSON-LD input document provided above would result in the following output:
{ "@context": { "name": "http://xmlns.com/foaf/0.1/name", "homepage": { "@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id" } }, "name": "Manu Sporny", "homepage": "http://manu.sporny.org/" }
The compaction algorithm also enables the developer to map any expanded
format into an application-specific compacted format. While the context
provided above mapped http://xmlns.com/foaf/0.1/name
to
name, it could have also mapped it to any arbitrary string
provided by the developer.
The algorithm takes three input variables: an active context, an active property, and an element to be compacted. To begin, the active context is set to the result of performing Context Processing on the passed context, active property is set to null, and element is set to the result of performing the Expansion Algorithm on the JSON-LD input. This removes any existing context to allow the given active context to be cleanly applied.
@value
property or element is a subject reference,
return the result of performing
Value Compaction on element using active property.@container
mapping to @list
and element has a corresponding @list
property, recursively compact that
property's value passing a copy of the active context and the active property ensuring
that the result is an array and removing null values. Return either the
result as an array, as an object with a key of @list
(or appropriate alias from
active context).@id
or @type
@container
mapping to @set
,
create an entry in output for active property and value as an
array.If, after the algorithm outlined above is run, the resulting element is an array, put element into the
@graph
property of a new JSON object and then set element to that JSON object.
Finally, add a @context
property to element and set it to the initially passed context.
JSON-LD Framing allows developers to query by example and force a specific tree layout to a JSON-LD document.
A JSON-LD document is a representation of a directed graph. A single directed graph can have many different serializations, each expressing exactly the same information. Developers typically work with trees, represented as JSON objects. While mapping a graph to a tree can be done, the layout of the end result must be specified in advance. A Frame can be used by a developer on a JSON-LD document to specify a deterministic layout for a graph.
Framing is the process of taking a JSON-LD document, which expresses a graph of information, and applying a specific graph layout (called a Frame).
Framing makes use of the Subject Flattening algorithm to place each object defined in the JSON-LD document into a flat list of objects, allowing them to be operated upon by the framing algorithm.
@id
to a parent JSON object and property
or parent array.This algorithm is a work in progress. Presently, it only works for documents without named graphs.
The framing algorithm takes an JSON-LD input (expanded input) and an input frame (expanded frame) that have been expanded according to the Expansion Algorithm, and a number of options and produces JSON-LD output.
Create framing context using null for the map of embeds, the object embed flag set to true, the explicit inclusion flag set to false, and the omit default flag set to false along with map of flattened subjects set to the result of performing Subject Flattening on expanded input. Also create results as an empty array.
Invoke the recursive algorithm using framing context (state), the map of flattened subjects (subjects), expanded frame (frame), result as parent, and null as active property.
The following series of steps is the recursive portion of the framing algorithm:
@type
property containing
one or more IRIs match any subject definition
with a @type
property including any of those IRIs.@type
property only
a empty JSON object, matches any subject definition
with a @type
property, regardless of the actual values.@embed
and @explicit
using the current values
for object embed flag and explicit inclusion flag from state if not found.@id
and id.@id
equal to id, element has
already been embedded and can be overwritten, so set embedOn to true.@list
, then
create a JSON object named list with the key @list
and
the value of an empty array. Append list to property in
output. Process each listitem in the @list
array as follows:
@id
of listitem as the key
and the subject definition from the original map of flattened subjects
as the value. Pass the first value from
frame for property as frame, list
as parent, and @list
as active property.@list
in list.@id
of item as the key and
the subject definition from the original map of flattened subjects
as the value. Pass the first value from
frame for property as frame, output
as parent, and property as active property.
@omitDefault
which is true or if it does not contain
@omitDefault
but the value of omit default flag
true.@preserve
and a value that is a copy of the value
of @default
in frame if it exists, or the string
@null
otherwise.At the completion of the recursive algorithm, results will contain the top-level subject definitions.
The final two steps of the framing algorithm require
results to be compacted according to the
Compaction Algorithm by using the
context provided in the input frame. If the frame has no context, compaction
is performed with an empty context (not a null context). The compaction result must use
the @graph
keyword at the top-level, even if the context is empty or if there
is only one element to put in the @graph
array. Subsequently, replace all key-value
pairs where the key is @preserve
with the value from the key-pair. If the value
from the key-pair is @null
, replace the value with null. If,
after replacement, an array contains only the value null remove the value, leaving
an empty array. The resulting value is the final JSON-LD output.
The algorithm needs to be updated to consider @graph
.
For 1.0, this might not require anything, as the default implementation of Subject Flattening should flatten everything
into a single graph.
Subject Flattening takes as input an expanded JSON-LD document, and results in a JSON object subjects with a mapping from each object represented in the document to a single entry within the input document, assigning blank node identifiers to objects without a @id, or with an @id that references a blank node identifier.
The algorithm operates on the initially empty subjects and takes as input the current document element.
@id
set to name as subject.
Otherwise, use that existing entrpy as subject.@id
:
property
and value
to subject
.@list.
Create a new JSON object containing
@list
and an array created by
performing this algorithm recursively on each item in the list
and add to subject along with property.The algorithm states to set the property in subject using the mapped values, but it really should merge, if the property already exists in subject.
The algorithm should descend into @graph and create a parallel flattened structure
of subject to object within that @graph
representation. Recursive @graph
definitions are also flattened into the default graph. The algorithm should also
take an option which descends into @graph
and flattens all definitions at the same level,
effectively flatting default and named graphs into a single default graph; this
should be the default implementation for 1.0.
This algorithm replaces an already embedded subject definition with a subject reference. It then recursively removes any entries in the map of embeds that had the removed subject definition in their parent chain.
The algorithm is invoked with a framing context and subject id id.
@id
of id,
removing that definition from the map, and then removing the dependents for the parent id
recursively by repeating this step. This step will terminate when there are no more embed
entries containing the removed subject definition's @id
in their
parent chain.This algorithm recursively embeds property values in subject definition output, given a framing context, input subject definition element, active property, and output.
@list
,
then create a new JSON object with a key @list
and
a value of an empty array and add it to output, appending if output
is an array, and appending to active property otherwise. Recursively call this
algorithm passing item as element, @list
as active property,
and the new array as output. Continue to the next item.@id
of item:
When coercing numbers to xsd:integer or xsd:double as it, e.g., happens during RDF Conversion, implementers must ensure that the result is a canonical lexical representation in the form of a string. A canonical lexical representation 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 representation and a value in the value space as defined in [XMLSCHEMA-2]. In other words, every value must be converted to a deterministic string representation.
The canonical lexical representation of an integer, i.e., a number without fractions
or a number coerced to xsd:integer, is a finite-length sequence of decimal
digits (0-9
) with an optional leading minus sign; leading zeroes are prohibited.
To convert the number in JavaScript, implementers can use the following snippet of code:
(value).toFixed(0).toString()
The canonical lexical representation of a double, i.e., a number with fractions
or a number coerced to xsd:double, consists of a mantissa followed by the
character "E", followed by an exponent. The mantissa must be a decimal number. The exponent
must be an integer. Leading zeroes and a preceding plus sign (+
) are prohibited
in the exponent. If the exponent is zero, it must be indicated by E0
.
For the mantissa, the preceding optional plus sign is prohibited and the decimal point is
required. Leading and trailing zeroes are prohibited subject to the following: number
representations must be normalized such that there is a single digit which is non-zero to the
left of the decimal point and at least a single digit to the right of the decimal point unless
the value being represented is zero. The canonical representation for zero is 0.0E0
.
To convert the number in JavaScript, implementers can use the following snippet of code:
(value).toExponential().replace(/e\+?/,'E')
xsd:double's value space is defined by the IEEE double-precision 64-bit floating point type [IEEE-754-1985].
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 representation directly.
When JSON-native datatypes, like numbers, are type coerced, lossless data round-tripping can not be guaranted. Consider the following code example:
var myObj1 = { "@context": { "number": { "@id": "http://example.com/vocab#number", "@type": "xsd:nonNegativeInteger" } }, "number" : 42 }; // Convert the JSON-LD document to RDF; this converts 42 to a string var jsonldText = jsonld.toRDF(myObj1, myRdfTripleCollector); // Convert the RDF triples back to a JavaScript object var myObj2 = jsonld.fromRDF(myRdfTripleCollector.getTriples());
At this point, myObj1
and myObj2
will have different
values for the "number" property. myObj1
will have the number
42
, while myObj2
have an object consisting of
@value
set to the string "42"
and @type
set to the expanded value of xsd:nonNegativeInteger.
Some JSON serializers, such as PHP's native implementation in some versions,
backslash-escape the forward slash character. For example, the value
http://example.com/
would be serialized as http:\/\/example.com\/
.
This is problematic as other JSON parsers might not understand those escaping characters.
There is no need to backslash-escape forward slashes in JSON-LD. To aid interoperability
between JSON-LD processors, a JSON-LD serializer must not backslash-escape forward slashes.
A JSON-LD document may be converted between other RDF-compatible document formats using the algorithms specified in this section.
The JSON-LD Processing Model describes processing rules for extracting RDF
from a JSON-LD document, and for transforming an array of Statement
retrieved by processing
another serialization format into JSON-LD. Note that many uses of JSON-LD may not require
generation of RDF.
The processing algorithms described in this section are provided in order to demonstrate how one might implement a JSON-LD to RDF processor. Conformant implementations are only required to produce the same type and number of statements during the output process and are not required to implement the algorithm exactly as described.
This section is non-normative.
JSON-LD is intended to have an easy to parse grammar that closely models existing practice in using JSON for describing object representations. This allows the use of existing libraries for parsing JSON.
As with other grammars used for describing Linked Data, a key concept is that of
a resource. Resources may be of three basic types: NamedNode
, representing
IRIs for describing
externally named entities, BlankNode
, resources for which an external name does not
exist, or is not known, and LiteralNode
, which describe terminal entities such as strings,
dates and other representations having a lexical representation possibly including
an explicit language or datatype.
An Internationalized Resource Identifier (IRI), as described in [RFC3987], is a mechanism for representing unique identifiers on the web. In Linked Data, an IRI is commonly used for expressing a subject, a property or an object.
Data described with JSON-LD may be considered to be the representation of a graph made up of subject and object resources related via a property resource. However, specific implementations may choose to operate on the document as a normal JSON description of objects having attributes.
The algorithm below is designed for in-memory implementations with random access to JSON object elements.
A conforming JSON-LD processor implementing RDF conversion must implement a
processing algorithm that results in the same set of RDF Statement
s that the following
algorithm generates:
The algorithm takes five input variables: a element to be converted, an active subject, active property and graph name. To begin, the active subject, active property and graph name are set to null, and element is set to the result of performing the Expansion Algorithm on the JSON-LD input. This removes any existing context to allow the given context to be cleanly applied.
@value
property, set the active object
to a literal value as follows:
@type
property
after performing IRI Expansion on the specified @type
.
@language
property, use it's value to set the language of the plain literal.
@list
property the value must be an array.
Process its value as a list as described in List Conversion using
the return value as the active object
Statement
representing active subject, active property,
active object, and graph name.@id
property,
the value must be a string, set the active subject to the previously
expanded value (either a blank node or an IRI).@id
property, set the active
subject to newly generated blank node.@type
, set the active property
to rdf:type
.
@graph
,
process value algorithm recursively, using active subject as graph name
and null values for active subject and active property and then
proceed to next property.xsd:integer
or xsd:double
, depending on if the value
contains a fractional and/or an exponential component.xsd:boolean
.Statement
using
active subject,active property, active object and
graph name.
List Conversion is the process of taking an array of values and adding them to a newly
created RDF Collection (see
[RDF-SCHEMA]) by linking each element of the list using rdf:first
and rdf:next
,
terminating the list with rdf:nil
using the following sequence:
The algorithm is invoked with an array array, the active property and returns a value to be used as an active object in the calling location.
rdf:nil
.
Statement
using using the active subject, active property
and a newly generated blank node identified as first blank node.
rdf:first
as the active property.
rdf:nil
.Statement
using first blank node,
rdf:rest
and rest blank node.In some cases, data exists natively in Triples or Quads form; for example, if the data was originally
represented in an RDF graph or triple/quad store. This algorithm is designed to simply translate
an array of Statement
s into a JSON-LD document.
The conversion algorithm takes a single parameter input in the form of an
array of Statement
representations.
rdf:first
.rdf:rest
.rdf:first
,
create a new entry in listMap with for name and subject and an array value
containing object representation and skip to the next statement.rdf:rest
,
and object is a BlankNode
,
create a new entry in restMap to map name and subject to a value being the
result of IRI expansion on object and skip to the next statement.@id
and
a string representation of name and use as value.@graph
, initialize it as a new array ary.name
and subject:
@id
and
a string representation of subject and use as value.@id
and
a string representation of subject and use as value.rdf:type
:
@type
, creating an entry in value if necessary.rdf:nil
:
@list
representation: {"@list": []}
.This section is non-normative.
This section is included merely for standards community review and will be submitted to the Internet Engineering Steering Group if this specification becomes a W3C Recommendation.
application/json
MIME media type.eval()
function. It is recommended that a conforming parser does not attempt to
directly evaluate the JSON-LD frame and instead purely parse the
input into a language-native data structure.The initial context is defined with the following default entries:
{ "@context": { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": { "@type": "@id"} } }
Processors must act as if the initial context is defined in the outer-most level when processing JSON-LD documents.
Should we define other default prefixes?
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, Dave Lehn and Mike Johnson who reviewed, provided feedback, and performed several implementations of the specification, and Ian Davis, who created RDF/JSON. Thanks also to Nathan Rixham, Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant, Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Niklas Lindström, Markus Lanthaler, and Richard Cyganiak for their input on the specification.