This document is also available in this non-normative format: diff to previous version
Copyright © 2010-2012 W3C ® ( MIT , ERCIM , Keio ), All Rights Reserved. W3C liability , trademark 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 section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at 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
transferred
to
the
RDF
Working
Group
for
review,
improvement,
and
publication
along
the
Recommendation
track.
While
this
is
a
First
Public
Working
Draft
publication,
the
The
specification
has
undergone
significant
development,
review,
and
changes
during
the
course
of
the
last
18
months
and
is
more
mature
than
the
First
Public
Working
Draft
status
implies.
months.
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.
There are a number of ways that one may participate in the development of this specification:
This
document
was
published
by
the
RDF
Working
Group
as
a
First
Public
Working
an
Editor's
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
an
Editor's
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 ].
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
four
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
read
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
node
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);
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
and
it
has
one
or
more
keys
other
than
@id
.
@id
key.
_:
.
The
JSON-LD
Processor
processor
interface
is
the
high-level
programming
structure
that
developers
use
to
access
the
JSON-LD
transformation
methods.
The
JSON-LD
API
signatures
are
the
same
across
all
programming
languages.
Due
to
the
fact
that
asynchronous
programming
is
uncommon
in
certain
languages,
developers
may
implement
a
processor
with
a
synchronous
interface
instead.
In
that
case,
the
callback
parameter
must
not
be
included
and
the
result
must
be
returned
as
a
return
value
instead.
[NoInterfaceObject]
interface JsonLdProcessor {
};
void expand (object or object[] or IRI input, object or IRI? context, JsonLdCallback
callback, optional JsonLdOptions
? options);
void compact (object or object[] or IRI input, object or IRI context, JsonLdCallback
callback, optional JsonLdOptions
? options);
void fromRDF (Quad
[] input, JsonLdCallback
callback, optional JsonLdOptions
? options);
void toRDF (object or object[] or IRI 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
@context
.
For
example,
if
a
@type
key
maps
to
anything
other
than
@id
or
an
absolute
IRI
,
this
error
would
be
returned
via
the
callback
.
@language
value.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
or
object[]
or
|
✘ | ✘ | 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
|
✘ | ✘ |
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
@context
.
For
example,
if
a
@type
key
maps
to
anything
other
than
@id
or
an
absolute
IRI
,
this
error
type
will
be
set
in
the
error
sent
to
the
callback
.Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
or
object[]
or
|
✘ | ✘ | 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
|
✔ | ✘ |
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
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.
@context
.
For
example,
if
a
@type
key
maps
to
anything
other
than
@id
or
an
absolute
IRI
,
this
error
will
be
returned.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
or
object[]
or
|
✘ | ✘ |
The
JSON-LD
object
or
array
of
JSON-LD
objects
to
convert
to
RDF
or
a
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
Developers should note that the details of error handling and conformance handling are being actively debated.
JSON-LD processors utilize a variety of callbacks in order to return information in an asynchronous manner to calling applications. This section details the parameters sent to those callbacks as well as the desired operation of the callbacks.
The
JsonLdError
type
is
used
to
encapsulate
a
variety
of
parameters
that
outline
the
cause
of
a
particular
JsonLdProcessor
error.
dictionary JsonLdProcessingError { string type; string operation; object or object[] source; string sourceKey; object or object[] or string or number sourceValue;
};
JsonLdProcessingError
Members
operation
of
type
string
compact
,
expand
,
toRDF
,
and
fromRDF
.
source
of
type
array
of
object
or
object
sourceKey
of
type
string
sourceValue
of
type
object
or
object[]
or
string
or
number
type
of
type
string
LIST_OF_LISTS_DETECTED
,
as
described
in
the
various
algorithms
in
this
document.
The
JsonLdCallback
is
used
to
return
a
processed
JSON-LD
representation
as
the
result
of
processing
an
API
method.
[NoInterfaceObject Callback]
interface JsonLdCallback {
};
void processingComplete (JsonLdProcessingError
error, object or object[] document);
};
jsonLd
processingComplete
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
|
| ✘ | ✘ |
If
the
value
is
null
,
then
no
error
occurred.
If
the
value
is
non-
null
,
a
processing
error
occurred
and
the
details
will
be
contained
within
the
error
object.
|
document |
object
or
object
[]
|
✘ | ✘ | The processed JSON-LD document. |
void
The
QuadCallback
is
called
whenever
the
processor
generates
a
quad
during
the
quad()
call.
processing.
[NoInterfaceObject Callback]
interface QuadCallback {
};
void quad (JsonLdProcessingError
error, Quad
quad);
};
quad
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
error |
| ✘ | ✘ |
If
the
value
is
null
,
then
no
error
occurred.
If
the
value
is
non-
null
,
a
processing
error
occurred
and
the
details
will
be
contained
within
the
error
object.
|
quad |
|
✘ | ✘ |
|
void
The
ConformanceCallback
may
be
specified
in
the
JsonLdOptions
via
the
conformanceCallback
parameter.
If
specified,
the
callback
is
called
whenever
a
recoverable
conformance
issue
is
detected.
The
developer
may
then
determine
whether
or
not
processing
should
continue
based
on
the
type
of
conformance
issue.
[NoInterfaceObject Callback]
interface ConformanceCallback {
void issue (JsonLdProcessingError
issue, function callback);
};
issue
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
issue |
| ✘ | ✘ | Details about the conformance issue. |
callback |
function
| ✘ | ✘ |
A
function
that
must
be
called
when
the
program
has
determined
how
to
respond
to
the
conformance
issue.
A
single
parameter
must
be
passed
to
the
callback.
The
value
of
the
parameter
should
be
null
if
processing
should
continue
by
acting
as
if
the
key-value
that
triggered
the
issue
never
existed.
The
issue
should
be
passed
to
the
callback
without
modification
if
processing
should
stop.
|
void
This section describes datatype definitions used within the JSON-LD API.
The
datatype
is
a
string
representation
of
an
IRI
.
URL
IRI
typedef
DOMString
URL
IRI
;
The
JsonLdOptions
type
is
used
to
convert
a
set
of
pass
various
options
to
an
interface
method.
the
typedef
JsonLdProcessor
object
JsonLdOptions
;
methods.
dictionary JsonLdOptions { IRI
? base; boolean compactArrays = true; boolean flatten = false; boolean optimize = false; boolean useRdfType = false; boolean useNativeTypes = true; function conformanceCallback = null;
};
URL
JsonLdOptions
Members
base
of
type
IRI
,
nullable
URL
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.
compactArrays
of
type
boolean
,
defaulting
to
true
true
,
the
JSON-LD
processor
replaces
arrays
with
just
one
element
with
that
element
during
compaction.
If
set
to
false
,
all
arrays
will
remain
arrays
even
if
they
have
just
one
element.
conformanceCallback
of
type
function
,
defaulting
to
null
null
,
the
processor
should
ignore
any
key-value
pair
associated
with
any
recoverable
conformance
issue
and
continue
processing.
More
details
about
this
feature
can
be
found
in
the
ConformanceCallback
section.
flatten
of
type
boolean
,
defaulting
to
false
object
false
,
the
JSON-LD
processor
must
modify
the
output
of
the
Compaction
Algorithm
or
the
Expansion
Algorithm
by
coalescing
all
properties
associated
with
each
subject
via
the
Flattening
Algorithm
.
The
value
of
flatten
must
be
either
an
IRI
value
representing
the
name
of
the
graph
to
flatten,
or
object[]
true
.
If
the
value
is
true
,
then
the
first
graph
encountered
in
the
input
document
is
selected
and
flattened.
optimize
of
type
boolean
,
defaulting
to
false
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.
useNativeTypes
of
type
boolean
true
true
,
the
JSON-LD
processor
will
@type
xsd:boolean
values
will
be
converted
to
true
or
false
.
xsd:integer
xsd:double
values
will
be
converted
to
JSON
numbers
.
useRdfType
of
type
boolean
,
defaulting
to
false
true
,
the
JSON-LD
processor
will
use
the
expanded
rdf:type
IRI
as
the
property
instead
of
@type
.
when
converting
from
RDF
.
The
following
data
structures
are
used
for
representing
data
about
RDF
quads.
They
are
used
for
normalization,
fromRDF
,
and
from
toRDF
interfaces.
RDF
conversion
.
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
property;
readonly attribute Node
object;
};
readonly attribute Node
? graph;
};
graphName
graph
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
property
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 {
};
};
[NoInterfaceObject]
interface IRI : Node
{
readonly attribute DOMString value;
};
};
value
of
type
DOMString
,
readonly
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;
};
};
datatype
of
type
IRI
,
readonly,
nullable
language
of
type
DOMString
,
readonly,
nullable
value
of
type
DOMString
,
readonly
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
.
stack.
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
with
the
lexical
form
described
in
[
BCP47
],
or
null
.
Add
the
language
to
the
local
context
.
@vocab
key,
it
must
have
a
value
of
a
simple
string
with
the
lexical
form
of
an
absolute
IRI
,
or
null
.
Add
the
vocabulary
mapping
to
the
local
context
.
@id
,
@language
or
@type
properties,
@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
expand
to
an
absolute
IRI
s.
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
IRIs
s
may
be
represented
as
an
absolute
IRI
,
a
term
or
,
a
compact
IRI
.
,
or
as
a
value
relative
to
@vocab
.
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:
@base
@type
and
the
active
context
has
a
@vocab
mapping,
join
the
mapped
value
to
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
,
and
value
is
null
,
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
.
@vocab
which
is
a
prefix
of
iri
where
the
resulting
relative
IRI
is
not
a
term
in
the
active
context
.
The
resulting
relative
IRI
is
the
unmatched
part
of
iri
.
@type
and
@vocab
is
not
null
and
matches
the
beginning
of
iri
,
return
the
unmatched
portion
of
iri
.
Otherwise
return
iri
.
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 ( expanded value ) 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
empty
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,
@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
:
@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,
@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.
compactArrays
option
is
set
to
true
,
the
compacted
value
is
that
item;
otherwise
the
compacted
value
is
element
.
@value
property
or
element
is
a
@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
@list
(or
appropriate
alias
from
,
return
an
error.
Otherwise
store
the
resulting
array
as
value
of
active
@id
or
@type
compactArrays
option
is
set
to
true
,
value
is
set
to
that
entry.
@container
mapping
to
@set
,
create
an
entry
in
output
for
active
property
or
if
the
compactArrays
and
option
is
set
to
false
,
convert
value
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
.
Flattening is the process of taking a JSON-LD document, expanding it, labeling all unlabeled nodes with a blank node identifier, and returning an array of the nodes defined in the document.
For example, assume the following JSON-LD input document:
{ "@context": { "name": "http://xmlns.com/foaf/0.1/name", "knows": "http://xmlns.com/foaf/0.1/knows" }, "@id": "http://example.com/markus", "name": "Markus Lanthaler", "knows": { "name": "Manu Sporny" } }
Running
the
JSON-LD
Flattening
algorithm
for
the
merged
graph
(
@merged
)
against
the
JSON-LD
input
document
provided
above
would
result
in
the
following
output:
[ { "@id": "http://example.com/markus", "http://xmlns.com/foaf/0.1/knows": [ { "@id": "_:t0" } ], "http://xmlns.com/foaf/0.1/name": [ { "@value": "Markus Lanthaler" } ] }, { "@id": "_:t0", "http://xmlns.com/foaf/0.1/name": [ { "@value": "Manu Sporny" } ] } ]
The
algorithm
takes
two
input
variables,
an
element
to
flatten
and
the
graph
for
which
the
node
definitions
should
be
returned.
If
graph
is
not
set,
it
will
default
to
@merged
which
represents
the
result
of
merging
all
graphs
including
the
default
graph
(
@default
).
The
Node
Map
Generation
algorithm
takes
as
input
an
expanded
JSON-LD
document
and
results
in
a
JSON
object
nodeMap
holding
a
flat
representation
of
the
graphs
and
nodes
represented
in
the
document.
All
nodes
that
are
not
uniquely
identified
by
an
IRI
get
assigned
a
(new)
blank
node
identifier.
The
resulting
nodeMap
document
will
have
a
property
for
every
graph
in
the
document
whose
value
is
another
object
with
a
property
for
every
node
represented
in
the
document.
While
the
default
graph
is
stored
under
the
@default
property
and
the
merged
graph
under
the
@merged
property,
all
other
graphs
are
stored
under
their
respective
IRIs
.
The
algorithm
takes
as
input
the
expanded
JSON-LD
document
as
element
,
the
initially
empty
nodeMap
,
@default
as
graph
,
null
as
list
,
and
null
as
id
.
@value
property,
then
if
list
is
not
null
,
append
element
to
list
and
return.
@id
property
exists
and
is
an
IRI
,
set
id
to
its
value,
otherwise
set
it
to
a
blank
node
identifier
created
by
the
Generate
Blank
Node
Identifier
algorithm.
@id
.
@id
.
Let
node
be
the
value
of
id
in
nodes
.
@id
and
each
value
in
element
ordered
by
property
:
@graph
,
recursively
call
this
algorithm
passing
value
for
element
,
nodeMap
,
null
for
list
and
if
graph
is
@merged
use
graph
,
otherwise
use
id
for
graph
and
then
continue.
@type
and
is
a
keyword,
merge
property
and
value
into
node
and
then
continue.
@id
is
not
an
IRI
or
it
does
not
exist,
map
v
to
a
new
blank
node
identifier
name
to
avoid
collisions.
If
one
does
not
already
exist,
add
a
node
reference
for
v
into
node
for
property
.
@list
then
recursively
call
this
algorithm
with
the
value
of
@list
as
element
,
nodeMap
,
graph
,
and
a
new
array
flattenedList
as
list
.
Create
a
new
JSON
object
with
the
property
@list
set
to
flattenedList
and
add
it
to
node
for
property
.
@type
and
v
is
not
an
IRI
,
generate
a
new
blank
node
identifier
and
add
it
to
node
for
property
.
After
the
above
outlined
algorithm
has
been
executed,
the
node
map
for
all
graphs
including
the
default
graph
are
contained
in
nodeMap
.
To
also
create
the
node
map
for
the
merged
graph,
execute
the
algorithm
again,
but
pass
@merged
for
graph
.
This algorithm is used by the Node Map Generation Algorithm to deterministically 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
.
The
default
value
of
prefix
is
_:t
.
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
node
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
node
definition
similar
to
Turtle's
blankNodePropertyList
.
After
expansion,
JSON-LD
numbers
,
booleans
,
typed-
and
language-tagged-
typed
literals
,
language-tagged-strings
,
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
four
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
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
useRdfType
option
is
@type
,
creating
an
entry
in
value
if
necessary.
useNativeTypes
option
is
set
to
true
:
xsd:boolean
,
the
converted
value
is
true
if
the
literal
matches
the
value
true
or
false
if
the
literal
matches
the
value
false
.
xsd:integer
or
xsd:double
,
try
to
convert
the
literal
to
a
JSON
number
.
If
the
conversion
is
successful,
store
the
result
in
converted
value
,
otherwise
set
converted
value
to
value
.
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
When
coercing
converting
JSON-LD
to
RDF
JSON-native
types
such
as
numbers
and
booleans
are
automatically
coerced
to
xsd:integer
or
,
xsd:double
as
it,
e.g.,
happens
during
RDF
Conversion
,
implementers
,
or
xsd:boolean
.
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
.
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().replace(/e\+?/,'E')(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
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",
}
},
"number" :
};
// 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"
guaranted
as
rounding
errors
might
occur.
Additionally,
only
literals
typed
as
xsd:integer
,
xsd:double
,
and
@type
set
xsd:boolean
are
automatically
converted
back
to
the
expanded
value
of
xsd:nonNegativeInteger
.
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
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
large
amount
of
an
initial
context
or
not.
If
JSON-LD
has
an
initial
context,
it
must
be
specified
external
thanks
goes
out
to
the
JSON-LD
Syntax
specification
at
a
well-known
location.
B.
Acknowledgements
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,
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,
RDFj.
The
work
of
Dave
Lehn
and
Mike
Johnson
who
reviewed,
provided
feedback,
are
appreciated
for
reviewing,
and
performed
performing
several
implementations
of
the
specification,
and
specification.
Ian
Davis,
who
created
Davis
is
thanked
for
this
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
for
their
input
on
the
specification.