This document is also available in this non-normative format: diff to previous version
Copyright
©
2010-2012
the
Contributors
to
the
JSON-LD
API
1.0
Specification,
published
by
the
JSON
for
Linking
Data
Community
Group
W3C
under
the
®
(
MIT
,
ERCIM
,
Keio
),
All
Rights
Reserved.
W3C
Community
Final
Specification
Agreement
(FSA)
.
A
human-readable
summary
liability
,
trademark
is
available.
and
document
use
rules
apply.
JSON [ RFC4627 ] has proven to be a highly useful object serialization and messaging format. JSON-LD [ JSON-LD ] harmonizes the representation of Linked Data in JSON by outlining a common JSON representation format for expressing directed graphs; mixing both Linked Data and non-Linked Data in a single document. This document outlines an Application Programming Interface and a set of algorithms for programmatically transforming JSON-LD documents in order to make them easier to work with in programming environments like JavaScript, Python, and Ruby.
This
specification
was
published
by
section
describes
the
JSON
for
Linking
Data
Community
Group
.
It
is
not
a
W3C
Standard
nor
is
it
on
status
of
this
document
at
the
time
of
its
publication.
Other
documents
may
supersede
this
document.
A
list
of
current
W3C
Standards
Track.
Please
note
that
under
publications
and
the
latest
revision
of
this
technical
report
can
be
found
in
the
W3C
Community
Final
Specification
Agreement
(FSA)
technical
reports
index
other
conditions
apply.
Learn
more
about
W3C
Community
and
Business
Groups
.
at
http://www.w3.org/TR/.
This
document
has
been
under
development
for
over
18
months
in
the
JSON
for
Linking
Data
Community
Group.
The
document
has
recently
been
approved
for
transfer
into
transferred
to
the
RDF
Working
Group
for
review
with
the
intent
to
publish
the
document
review,
improvement,
and
publication
along
the
W3C
Recommendation
track.
This
While
this
is
a
First
Public
Working
Draft
publication,
the
specification
has
undergone
significant
development,
review,
and
changes
during
the
course
of
the
last
18
months
and
is
being
published
as
a
Final
Community
Group
Specification
so
that
it
may
gain
wider
review
and
feedback.
more
mature
than
the
First
Public
Working
Draft
status
implies.
There are currently five interoperable implementations of this specification. There is a fairly complete test suite and a live JSON-LD editor that is capable of demonstrating the features described in this document. While development on implementations, the test suite and the live editor will continue, they are believed to be mature enough to be integrated into a non-production system at this point in time with the expectation that they could be used in a production system within the next year.
It is important for readers to understand that the scope of this document is currently under debate and new features may be added to the specification. Existing features may be modified heavily or removed entirely from the specification upon further review and feedback from the broader community. This is a work in progress and publication as a First Public Working Draft does not require that all Working Group members agree on the content of the document.
This document was published by the RDF Working Group as a First Public Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-rdf-comments@w3.org ( subscribe , archives ). All feedback is welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is a detailed specification for an Application Programming Interface for the JSON-LD Syntax. The document is primarily intended for the following audiences:
To understand the basics in this specification you must first be familiar with JSON, which is detailed in [ RFC4627 ]. You must also understand the JSON-LD Syntax [ JSON-LD ], which is the base syntax used by all of the algorithms in this document. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ ECMA-262 ] and WebIDL [ WEBIDL ]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [ RDF-CONCEPTS ].
There are a number of ways that one may participate in the development of this specification:
The JSON-LD Syntax specification [ JSON-LD ] outlines a language that may be used to express Linked Data in JSON. Often, it is useful to be able to transform JSON-LD documents so that they may be easily processed in a programming environment like JavaScript, Python or Ruby.
There are three major types of transformation that are discussed in this document; compaction, expansion, and RDF conversion.
Software algorithms are easiest to write when the data that they are processing have a regular form. Since information can be represented by JSON-LD in a variety of different ways, transforming all of these methods into a uniform structure allows the developer to simplify their processing code. For example, note that the following input uses only term s and is fairly compact:
var input1 = { "@context": "http://json-ld.org/contexts/person.jsonld" "name": "Manu Sporny", "homepage": "http://manu.sporny.org/" }
The next input example uses one IRI to express a property, but leaves the rest of the information untouched.
var input2 = {
"@context": "http://json-ld.org/contexts/person.jsonld"
"http://xmlns.com/foaf/0.1/name": "Manu Sporny",
"homepage": "http://manu.sporny.org/"
}
While both inputs are valid JSON-LD, writing a program to handle every permutation of possible inputs can be difficult, especially when the incoming context could change as well. To ensure that the data can be given a more uniform structure, JSON-LD introduces the notion of expansion. Expansion performs two important operations. The first is to expand all values that are IRI s to their fully expanded form. The second is to express all values in expanded form . To transform both inputs above to the same representation, the developer could do the following:
function expansionCallback(output) { console.log(output); } // the second parameter is 'null' because the developer does not wish to // inject another context value jsonld.expand(input1, null, expansionCallback); jsonld.expand(input2, null, expansionCallback);
The output for both calls above will be:
[{ "http://xmlns.com/foaf/0.1/name": [{ "@value": "Manu Sporny" }], "http://xmlns.com/foaf/0.1/homepage": [{ "@id": "http://manu.sporny.org/" }] }]
Note that in the example above; all context definitions have been removed, all term and prefixes have been expanded to full IRIs, and all literal s are expressed in expanded form . While the output is more difficult for a human to read, it is easier for a software program to process because of its very regular structure.
While expansion expands a given input as much as possible, compaction performs the opposite operation - expressing a given input as succinctly as possible. While expansion is meant to produce something that is easy to process by software programs, compaction is meant to produce something that is easy to ready by software developers. Compaction uses a developer-supplied context to compresses all IRI s to term s or prefix es, and compacts all literal s expressed in expanded form as much as possible.
The following example expresses input that has already been fully expanded:
var expandedInput = [{ "http://xmlns.com/foaf/0.1/name": [{ "@value": "Manu Sporny" }], "http://xmlns.com/foaf/0.1/homepage": [{ "@id": "http://manu.sporny.org/" }] }]
A developer that wants to transform the data above into a more human-readable form, could do the following using the JSON-LD API:
function compactionCallback(output) { console.log(output); } jsonld.compact(expandedInput, "http://json-ld.org/contexts/person.jsonld", compactionCallback);
The following would be the result of the call above:
{ "@context": "http://json-ld.org/contexts/person.jsonld" "name": "Manu Sporny", "homepage": "http://manu.sporny.org/" }
Note that all of the term s have been compressed and the context has been injected into the output. While compacted output is most useful to humans, it can also be carefully used to generate structures that are easy to use for developers to program against as well.
JSON-LD can be used to losslessly express the RDF data model as described in the RDF Concepts document [ RDF-CONCEPTS ]. This ensures that data can be round-tripped from any RDF syntax, like N-Triples or TURTLE, without any loss in the fidelity of the data. Assume the following RDF input in N-Triples format:
var data = " <http://manu.sporny.org/about/#manu> <http://xmlns.com/foaf/0.1/name> \"Manu Sporny\" .\n <http://manu.sporny.org/about/#manu> <http://xmlns.com/foaf/0.1/homepage> <http://manu.sporny.org/> .";
A developer can use the JSON-LD API to transform the markup above into a JSON-LD document:
function conversionCallback(result) { console.log("JSON-LD Document: ", result); }; jsonld.fromRDF(data, conversionCallback, {"format": "ntriples"});
The following expanded output would be the result of the call above:
[{ "@id": "http://manu.sporny.org/about/#manu", "http://xmlns.com/foaf/0.1/name": [{ "@value": "Manu Sporny" }], "http://xmlns.com/foaf/0.1/homepage": [{ "@id": "http://manu.sporny.org/" }] }]
Note that the output above, could easily be compacted to produce the following using the technique outlined in the previous section:
{ "@context": "http://json-ld.org/contexts/person.jsonld", "@id": "http://manu.sporny.org/about/#manu", "name": "Manu Sporny", "homepage": "http://manu.sporny.org/" }
Transforming
the
object
above
back
to
RDF
is
as
simple
as
calling
the
toRDF()
method:
var jsonldDocument = ...; // assign the JSON-LD document here function rdfCallback(quads) { console.log("RDF Data: ", quads); }; jsonld.toRDF(jsonldDocument, rdfCallback);
There are currently two other API methods that are in active development and were not ready for publication at the time this document was published. Framing allows a developer to force a different layout for the data and effectively perform query-by-example on JSON-LD documents - this is most useful when a JSON-LD-based REST API does not know the exact form of the data it is getting in, but still wants to operate upon it if some bare essentials are found in the data. JSON-LD normalization allows JSON-LD documents to be deterministically serialized such that they can be digitally signed or be used to find the differences between two linked data graph s. It is expected that framing will be a part of the final API. It is expected that normalization will be an optional feature that JSON-LD processors may implement.
This API provides a clean mechanism that enables developers to convert JSON-LD data into a a variety of output formats that are easier to work with in various programming languages. If a JSON-LD API is provided in a programming environment, the entirety of the following API must be implemented.
The intent of the Working Group and the Editors of this specification is to eventually align terminology used in this document with the terminology used in the RDF Concepts document to the extent to which it makes sense to do so. In general, if there is an analogue to terminology used in this document in the RDF Concepts document, the preference is to use the terminology in the RDF Concepts document.
The following is an explanation of the general terminology used in this document:
@value
,
@list
,
or
@set
is
set
to
null
in
expanded
form,
then
the
entire
JSON
object
is
ignored.
If
@context
is
set
to
null
,
the
active
context
is
reset
and
when
used
within
a
context
,
it
removes
any
definition
associated
with
the
key,
unless
otherwise
specified.
@value
,
@list
or
@set
and
it
has
one
or
more
keys
other
than
@id
.
@id
key.
The JSON-LD Processor interface is the high-level programming structure that developers use to access the JSON-LD transformation methods.
[NoInterfaceObject]
interface JsonLdProcessor {
void expand (object or object[] or URL input, object or URL? context, JsonLdCallback
callback, optional JsonLdOptions
options);
void compact (object or object[] or URL input, object or URL context, JsonLdCallback
callback, optional JsonLdOptions
options);
void fromRDF (Quad
[] input, JsonLdCallback
callback, optional JsonLdOptions
options);
void toRDF (object or object[] or URL input, QuadCallback
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
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 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. |
context |
object
or
URL
|
✔ | ✘ |
An
optional
external
context
to
use
additionally
to
the
context
embedded
in
input
when
expanding
the
input
.
|
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
fromRDF
Quads
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
|
✘ | ✘ |
A
dataset
represented
as
an
array
of
Quads
.
|
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
Quad
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
a
URL
referencing
the
JSON-LD
document
to
convert
to
RDF.
|
callback |
|
✘ | ✘ |
A
callback
that
is
called
when
a
Quad
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 (object or object[] jsonld);
};
jsonLd
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
jsonld |
object
or
object
[]
|
✘ | ✘ | The processed JSON-LD document. |
void
The
QuadCallback
is
called
whenever
the
processor
generates
a
quad
during
the
quad()
call.
[NoInterfaceObject Callback]
interface QuadCallback {
void quad (Quad
quad);
};
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
JsonLdOptions
type
is
used
to
convert
a
set
of
options
to
an
interface
method.
typedef
object
JsonLdOptions
;
URL
base
URL
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 quads. They are used for normalization, fromRDF , and from toRDF interfaces.
The
Quad
interface
represents
an
RDF
Quad.
See
[
RDF-CONCEPTS
]
definition
for
RDF
triple
,
which
most
closely
aligns
to
Quad
.
[NoInterfaceObject]
interface Quad {
readonly attribute Node
subject;
readonly attribute Node
predicate;
readonly attribute Node
object;
readonly attribute Node
? graphName;
};
graphName
of
type
Node
,
readonly,
nullable
Quad
identifying
it
as
a
member
of
a
named
graph
.
If
it
is
missing,
the
quad
is
a
member
of
the
default
graph
.
object
of
type
Node
,
readonly
Quad
.
predicate
of
type
Node
,
readonly
Quad
.
Within
JSON-LD,
an
RDF
predicate
is
refered
to
as
a
property
subject
of
type
Node
,
readonly
Quad
.
Node
is
the
base
class
of
IRI
,
BlankNode
,
and
Literal
.
It
is
the
IDL
representation
of
a
linked
data
graph
node
.
[NoInterfaceObject]
interface Node {
};
A
node
in
the
linked
data
graph
that
does
not
contain
a
de-reference-able
identifier
because
it
is
either
ephemeral
in
nature
or
does
not
contain
information
that
needs
to
be
linked
to
from
outside
of
the
linked
data
graph
.
A
blank
node
is
assigned
an
identifier
starting
with
the
prefix
_:
and
an
implementation
dependent,
auto-generated
suffix
that
is
unique
to
all
information
associated
with
the
particular
blank
node.
[NoInterfaceObject]
interface BlankNode : Node
{
readonly attribute DOMString identifier;
};
identifier
of
type
DOMString
,
readonly
identifier
must
not
be
relied
upon
in
any
way
between
two
separate
processing
runs
of
the
same
document
or
with
a
different
document.
Developers
and
authors
must
not
assume
that
the
value
of
a
blank
node
will
remain
the
same
between
two
processing
runs.
BlankNode
values
are
only
valid
for
the
most
recent
processing
run
on
the
document.
BlankNode
values
will
often
be
generated
differently
by
different
processors.
Implementers
must
ensure
that
BlankNode
values
are
unique
within
the
current
environment,
two
BlankNodes
are
considered
equal
if,
and
only
if,
their
values
are
strictly
equal.
Literals
represent
values
such
as
numbers,
dates
and
strings
in
RDF
data.
A
Literal
is
comprised
of
three
attributes:
value
language
tag
datatype
specified
by
an
IRI
Literals
representing
plain
text
in
a
natural
language
may
have
a
language
tag
specified
by
a
string
token,
as
specified
in
[
BCP47
],
normalized
to
lowercase
(e.g.,
'en'
,
'fr'
,
'en-gb'
).
They
also
have
a
datatype
attribute
such
as
xsd:string
.
If
unspecified,
the
datatype
defaults
to
xsd:string
.
Literals
representing
values
with
a
specific
datatype,
such
as
the
integer
72,
may
have
a
datatype
attribute
specified
in
the
form
of
a
IRI
(e.g.,
xsd:integer
).
See[ RDF-CONCEPTS ] definition for literal .
[NoInterfaceObject]
interface Literal : Node
{
readonly attribute DOMString value;
readonly attribute DOMString? language;
readonly attribute IRI
? datatype;
};
All algorithms described in this section are intended to operate on language-native data structures. That is, the serialization to a text-based JSON document isn't required as input or output to any of these algorithms and language-native data structures must be used where applicable.
@context
keyword
.
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 an array) using a term mapping . It is also used to maintain coercion mapping s from terms to datatypes, language mapping s from terms to language codes, and list mapping s and set mapping s for terms. Processors must use the lexical form of the property when creating a mapping, as lookup is performed on lexical forms, 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,
its
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,
its
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 IRI s.
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 .
IRI s 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 IRI s. This section defines an algorithm for transforming an IRI ( iri ) to a term or compact IRI using the term s 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
a
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
:
@value
.
@value
property:
@type
property
matching
a
@type
coercion
for
term
,
term
rank
is
3
,
otherwise
if
term
has
no
@type
coercion
and
no
@language
,
term
rank
is
1
,
otherwise
0
.
@value
is
not
a
string
,
if
term
has
no
@type
or
@language
it
is
2
,
otherwise
1
.
@language
property,
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
.
@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
coercion
and
no
@language
,
term
rank
is
1
,
otherwise
0
.
@type
coerced
to
@id
,
term
rank
is
3
,
otherwise
if
term
has
no
@type
coercion
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:
@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
.
@type
and
the
associated
coercion
datatype
expanded
according
to
the
IRI
Expansion
rules.
@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
.
@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.
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 other JSON-LD API methods.
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 result of performing, Context Processing on the passed context , or to the initial context if context is null , 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
its
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
or
@set
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
its
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
.
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
Quad
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 quads 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
node
in
a
linked
data
graph
.
Nodes
may
be
of
three
basic
types.
The
first
is
the
IRI
,
which
is
used
to
refer
to
node
s
in
other
linked
data
graph
s.
The
second
is
the
blank
node
,
which
are
nodes
for
which
an
external
name
does
not
exist,
or
is
not
known.
The
third
is
a
Literal
,
which
express
values
such
as
strings,
dates
and
other
information
having
a
lexical
form,
possibly
including
an
explicit
language
or
datatype.
Data described with JSON-LD may be considered to be a graph made up of subject and object nodes related via a property node . Specific implementations may also choose to operate on the document as a normal JSON description of objects having attributes. Both approaches are valid ways to interact with JSON-LD documents.
This section is non-normative.
The following examples show simple transformations of JSON-LD documents to Turtle [ TURTLE-TR ].
The first example uses a simple document containing a simple FOAF profile:
{ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"}, "@id": "http://greggkellogg.net/foaf#me", "@type": "foaf:Person", "foaf:name": "Gregg Kellogg", "foaf:knows": { "@type": "foaf:Person", "foaf:name": "Manu Sporny" } }
This translates fairly directly to a similar Turtle document:
@prefix foaf: <http://xmlns.com/foaf/0.1/>. <http://greggkellogg.net/foaf#me> a foaf:Person; foaf:name "Gregg Kellogg"; foaf:knows [ a foaf:Person; foaf:name "Manu Sporny"].
The
actual
parsing
steps
first
require
that
the
JSON-LD
document
be
expanded,
to
eliminate
the
@context
:
[{ "@id": "http://greggkellogg.net/foaf#me", "@type": ["http://xmlns.com/foaf/0.1/Person"], "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], "http://xmlns.com/foaf/0.1/knows": [{ "@type": ["http://xmlns.com/foaf/0.1/Person"], "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}] }] }]
The
process
of
translating
this
to
RDF
then
operates
over
each
subject
definition
to
find
a
subject,
each
property
to
find
an
RDF
predicate
,
and
each
value
of
that
property
to
find
an
object
.
In
this
case,
each
property
has
just
a
single
object:
foaf:name
identifies
a
literal
,
and
foaf:knows
identifies
a
second
subject
definition
similar
to
Turtle's
blankNodePropertyList
.
After expansion, JSON-LD numbers , booleans , typed- and language-tagged- literals , and IRIs become explicit, and can be directly transformed into their RDF representations.
[{
"@id": "http://greggkellogg.net/foaf#me",
"@type": ["http://xmlns.com/foaf/0.1/Person"],
"http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}],
"http://xmlns.com/foaf/0.1/currentProject": [{"@id": "http://json-ld.org/"}],
"http://xmlns.com/foaf/0.1/birthday": [{
"@value": "1957-02-27",
"@type": "http://www.w3.org/2001/XMLSchema#date"
}],
"http://xmlns.com/foaf/0.1/knows": [{
"@type": ["http://xmlns.com/foaf/0.1/Person"],
"http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}]
}]
}]
Translates to:
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
<http://greggkellogg.net/foaf#me> a foaf:Person;
foaf:name "Gregg Kellogg";
foaf:currentProject <http://json-ld.org/>;
foaf:birthday "1957-02-27"^^xsd:date;
foaf:knows
[
a
foaf:Person;
foaf:name
"Manu
Sporny"].
The algorithm below is designed for in-memory implementations with random access to JSON object elements.
A conforming JSON-LD processor implementing RDF conversion must implement a processing algorithm that results in the same set of RDF Quads that the following algorithm generates:
The algorithm takes 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:
@value
is
a
number
,
set
the
active
object
to
a
typed
literal
using
a
string
representation
of
the
value
as
defined
in
the
section
Data
Round
Tripping
.
Set
datatype
to
the
value
of
the
@type
property
if
it
exists,
otherwise
either
xsd:integer
or
xsd:double
,
depending
on
if
the
value
contains
a
fractional
and/or
an
exponential
component.
@value
is
true
or
false
,
set
the
active
object
to
a
typed
literal
created
from
the
string
representation
of
the
value.
Set
datatype
to
the
value
of
the
@type
property
if
it
exists,
otherwise
xsd:boolean
.
@type
property,
set
the
active
object
to
a
typed
literal
.
@language
property,
set
the
active
object
to
a
language-tagged
literal
.
xsd:string
as
the
datatype.
@list
property
the
value
must
be
an
array
.
Process
its
value
as
a
list
as
described
in
List
Conversion
using
the
return
value
as
the
active
object
Quad
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.
rdf:type
so
set
the
active
object
to
an
IRI
.
Quad
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
.
Quad
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
.
Quad
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
Quads
into
a
JSON-LD
document.
When
expanding
typed
literal
values
having
a
datatype
of
xsd:string
,
the
@type
must
not
be
set
to
xsd:string
and
the
resulting
value
must
have
only
a
@value
property.
The
conversion
algorithm
takes
a
single
parameter
input
in
the
form
of
an
array
of
Quad
representations.
rdf:first
,
use
the
entry
in
graph.listMap
indexed
by
subject
,
initializing
it
to
a
new
JSON
object
if
nesessary.
Represent
object
in
expanded
form,
as
described
in
Value
Expansion
.
Add
the
resulting
object
representation
to
the
entry
indexed
by
first
,
and
skip
to
the
next
quad.
rdf:rest
:
@id
and
a
string
representation
of
name
.
@id
and
a
string
representation
of
subject
if
necessary.
rdf:type
and
the
notType
option
is
present
and
not
true
:
@type
,
creating
an
entry
in
value
if
necessary.
rdf:nil
:
@list
representation
to
the
array
value
for
key
,
creating
an
entry
in
value
if
necessary.
@id
in
value
.
@list
initialized
to
a
new
array
containing
the
value
of
first
from
entry
.
@graph
in
entry
containing
the
ordered
entries
from
graphs[subject].subjects
.
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 form in the form of a string . A canonical lexical form is a set of literals from among the valid set of literals for a datatype such that there is a one-to-one mapping between the canonical lexical form and a value in the value space as defined in [ XMLSCHEMA11-2 ]]. In other words, every value must be converted to a deterministic string representation.
The
canonical
lexical
form
of
an
integer
,
i.e.,
a
number
without
fractions
or
a
number
coerced
to
xsd:integer
,
is
a
finite-length
sequence
of
decimal
digits
(
0-9
)
with
an
optional
leading
minus
sign;
leading
zeroes
are
prohibited.
To
convert
the
number
in
JavaScript,
implementers
can
use
the
following
snippet
of
code:
(value).toFixed(0).toString()
The
canonical
lexical
form
of
a
double
,
i.e.,
a
number
with
fractions
or
a
number
coerced
to
xsd:double
,
consists
of
a
mantissa
followed
by
the
character
"E",
followed
by
an
exponent.
The
mantissa
must
be
a
decimal
number.
The
exponent
must
be
an
integer.
Leading
zeroes
and
a
preceding
plus
sign
(
+
)
are
prohibited
in
the
exponent.
If
the
exponent
is
zero,
it
must
be
indicated
by
E0
.
For
the
mantissa,
the
preceding
optional
plus
sign
is
prohibited
and
the
decimal
point
is
required.
Leading
and
trailing
zeroes
are
prohibited
subject
to
the
following:
number
representations
must
be
normalized
such
that
there
is
a
single
digit
which
is
non-zero
to
the
left
of
the
decimal
point
and
at
least
a
single
digit
to
the
right
of
the
decimal
point
unless
the
value
being
represented
is
zero.
The
canonical
representation
for
zero
is
0.0E0
.
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 form directly.
When JSON-native datatypes, like number s, 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.
It is still being discussed whether JSON-LD has the notion of an initial context or not. If JSON-LD has an initial context, it must be specified external to the JSON-LD Syntax specification at a well-known location.
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, Josh Mandel, Eric Prud'hommeaux, David Wood, Guus Schreiber, Pat Hayes, Sandro Hawke, and Richard Cyganiak for their input on the specification.