This document is also available in this non-normative format: diff to previous version .
This document is licensed under a Creative Commons Attribution 3.0 License .
JSON [ RFC4627 ] has proven to be a highly useful object serialization and messaging format. JSON-LD [ JSON-LD ] harmonizes the representation of Linked Data in JSON by outlining a common JSON representation format for expressing directed graphs; mixing both Linked Data and non-Linked Data in a single document. This document outlines an Application Programming Interface and a set of algorithms for programmatically transforming JSON-LD documents.
This document is merely a public working draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organisation.
This document is an experimental work in progress.
JSON, as specified in [ RFC4627 ], is a simple language for representing data on the Web. Linked Data is a technique for creating a graph of interlinked data across different documents or Web sites. Data entities are described using IRI s, which are typically dereferencable and thus may be used to find more information about an entity, creating a "Web of Knowledge". JSON-LD is intended to be a simple publishing method for expressing not only Linked Data in JSON, but also for adding semantics to existing JSON.
JSON-LD is designed as a light-weight syntax that can be used to express Linked Data. It is primarily intended to be a way to use Linked Data in Javascript and other Web-based programming environments. It is also useful when building interoperable Web services and when storing Linked Data in JSON-based document storage engines. It is practical and designed to be as simple as possible, utilizing the large number of JSON parsers and libraries available today. It is designed to be able to express key-value pairs, RDF data, RDFa [ RDFA-CORE ] data, Microformats [ MICROFORMATS ] data, and Microdata [ MICRODATA ]. That is, it supports every major Web-based structured data model in use today.
The syntax does not necessarily require applications to change their JSON, but allows to easily add meaning by adding context in a way that is either in-band or out-of-band. The syntax is designed to not disturb already deployed systems running on JSON, but provide a smooth upgrade path from JSON to JSON with added semantics. Finally, the format is intended to be easy to parse, efficient to generate, convertible to RDF in one pass, and require a very small memory footprint in order to operate.
This document is a detailed specification for a serialization of Linked Data in JSON. The document is primarily intended for the following audiences:
To understand the basics in this specification you must first be familiar with JSON, which is detailed in [ RFC4627 ]. You must also understand the JSON-LD Syntax [ JSON-LD ], which is the base syntax used by all of the algorithms in this document. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ ECMA-262 ] and WebIDL [ WEBIDL ]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [ RDF-CONCEPTS ].
Examples
may
contain
references
to
existing
vocabularies
and
use
prefix
es
to
refer
to
Web
Vocabularies.
vocabularies.
The
following
is
a
list
of
all
vocabularies
and
their
prefix
abbreviations,
as
used
in
this
document:
dc
,
e.g.,
dc:title
)
foaf
,
e.g.,
foaf:knows
)
rdf
,
e.g.,
rdf:type
)
xsd
,
e.g.,
xsd:integer
)
JSON [ RFC4627 ] defines several terms which are used throughout this document:
@value
,
@list
or
@set
and
it
has
one
or
more
keys
other
than
@id
.
@id
key.
The following definition for Linked Data is the one that will be used for this specification.
Note that the definition for Linked Data above is silent on the topic of unlabeled nodes. Unlabeled nodes are not considered Linked Data . However, this specification allows for the expression of unlabled nodes, as most graph-based data sets on the Web contain a number of associated nodes that are not named and thus are not directly de-referenceable.
There are a number of ways that one may participate in the development of this specification:
This API provides a clean mechanism that enables developers to convert JSON-LD data into a a variety of output formats that are easier to work with in various programming languages. If a JSON-LD API is provided in a programming environment, the entirety of the following API must be implemented.
[NoInterfaceObject]
interface JsonLdProcessor {
void expand (object or object[] or URL input, JsonLdCallback
callback, optional JsonLdOptions
options);
void compact (object or object[] or URL input, object or URL context, JsonLdCallback
callback, optional JsonLdOptions
options);
void frame (object or object[] or URL input, object or URL frame, JsonLdCallback
callback, optional JsonLdOptions
options);
void fromRDF (Statement
[] input, JsonLdCallback
callback, optional JsonLdOptions
options);
void toRDF (object or object[] or URL input, ObjectOrURL? context, StatementCallback
callback, optional JsonLdOptions
options);
};
compact
input
using
the
context
according
to
the
steps
in
the
Compaction
Algorithm
.
The
input
must
be
copied,
compacted
and
returned
if
there
are
no
errors.
If
the
compaction
fails,
an
appropirate
exception
must
be
thrown.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
or
object[]
or
URL
|
✘ | ✘ |
The
JSON-LD
object
or
array
of
JSON-LD
objects
to
perform
the
compaction
|
context |
object
or
URL
|
✘ | ✘ |
The
input
;
either
in
the
form
of
an
JSON
object
or
as
|
callback |
|
✘ | ✘ |
A
callback
that
is
called
when
processing
is
complete
on
the
given
input
.
|
options |
|
✘ | ✔ |
A
set
of
options
that
may
affect
the
optimize
,
which
if
set
will
cause
processor-specific
optimization.
|
object
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
|
|
|
✘ | ✘ |
input
.
|
options |
|
✘ | ✔ | A set of options that may affect the expansion algorithm such as, e.g., the input document's base IRI . |
object
void
frame
input
using
the
frame
according
to
the
steps
in
the
Framing
Algorithm
.
The
input
is
used
to
build
the
framed
output
and
is
returned
if
there
are
no
errors.
If
there
are
no
matches
for
the
frame,
null
must
be
returned.
Exceptions
must
be
thrown
if
there
are
errors.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
or
object[]
or
URL
|
✘ | ✘ |
The
JSON-LD
object
or
array
of
JSON-LD
objects
to
perform
the
framing
|
frame |
object
or
URL
|
✘ | ✘ |
The
frame
to
use
when
re-arranging
the
input
;
either
in
the
form
of
an
JSON
object
or
as
IRI
.
|
|
|
✘ | ✘ |
A
input
.
|
options |
|
✘ | ✔ |
A
|
object
void
normalize
fromRDF
input
according
to
the
steps
in
the
Normalization
Algorithm
.
The
input
must
be
copied,
normalized
and
returned
if
there
are
no
errors.
If
the
compaction
fails,
null
Statement
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
|
✘ | ✘ |
|
|
|
✘ | ✘ |
input
.
|
options |
|
✘ | ✔ |
A
,
which
if
@type
.
|
DOMString
void
triples
toRDF
input
according
to
the
Convert
to
RDF
tripleCallback
callback
for
each
Statement
generated.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
or
object[]
or
URL
|
✘ | ✘ |
The
JSON-LD
object
or
array
of
JSON-LD
objects
to
|
context |
ObjectOrURL
| ✔ | ✘ |
An
external
context
to
use
additionally
to
the
context
embedded
in
input
when
input
.
|
|
|
✘ | ✘ |
A
callback
that
is
called
Statement
is
created
from
processing
input
.
|
|
|
✘ | ✔ |
|
InvalidContext
void
The
A
general
syntax
error
was
detected
in
the
@context
.
For
example,
if
a
@type
JsonLdCallback
key
maps
is
used
to
anything
other
than
return
a
processed
JSON-LD
representation
as
the
result
of
processing
an
API
method.
[NoInterfaceObject Callback]
interface JsonLdCallback {
void jsonLd (ObjectOrObjectArray jsonld);
};
@id
jsonLd
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
jsonld |
|
✘ | ✘ | The processed JSON-LD document. |
void
The
JsonLdTripleCallback
StatementCallback
is
called
whenever
the
processor
generates
a
triple
statement
during
the
call.
triple()
statement()
[NoInterfaceObject Callback]
interface StatementCallback {
void statement (Statement
statement);
};
triple
statement
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
|
|
✘ | ✘ |
The
|
DOMString
void
This section describes datatype definitions used within the JSON-LD API.
The
property
URL
datatype
is
a
string
representation
of
an
IRI
.
typedef
DOMString
URL
;
JSON
object
or
array
.The JsonLdOptiones type is used to convery a set of options to an interface method.
typedef
object
JsonLdOptions
;
URL
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
statements
(triples
or
quads).
They
are
used
for
normalization,
DOMString
fromRDF
,
and
from
toRDF
interfaces.
The
Statement
interface
represents
an
RDF
Statement.
[NoInterfaceObject]
interface Statement {
readonly attribute Node
subject; readonly attribute Node
property; readonly attribute Node
object; readonly attribute Node
? name;
};
name
of
type
Node
,
readonly,
nullable
Statement
identifying
it
as
a
member
of
object
literal
.
Node
,
readonly
Statement
.
property
of
type
Node
Statement
.
subject
of
type
Node
,
readonly
Statement
.
Node
is
the
base
class
of
NamedNode
,
BlankNode
,
and
LiteralNode
.
[NoInterfaceObject]
interface Node {
readonly attribute DOMString nominalValue; readonly attribute DOMString interfaceName;
};
interfaceName
of
type
DOMString
,
readonly
Provides
access
to
the
property.
string
name
of
the
current
interface,
normally
one
of
"
IRI
"
,
"BlankNode"
or
"LiteralNode"
.
This
method
serves
to
disambiguate
instances
of
Node
which
are
otherwise
identical,
such
as
datatype
NamedNode
and
BlankNode
.
nominalValue
of
type
DOMString
,
readonly
The
nominalValue
of
an
Node
✔
is
refined
by
each
interface
which
extends
✘
Node
.
A node identified by an IRI . NamedNodes are defined by International Resource Identifier [ IRI ].
[NoInterfaceObject]
interface NamedNode : Node
{
readonly attribute DOMString nominalValue;
};
nominalValue
of
type
DOMString
,
readonly
A
BlankNode
is
a
reference
to
an
unnamed
resource
(one
for
which
an
IRI
is
not
known),
and
may
be
used
in
a
Statement
as
a
unique
reference
to
that
unnamed
resource.
[NoInterfaceObject]
interface BlankNode : Node
{
readonly attribute DOMString nominalValue;
};
nominalValue
of
type
DOMString
,
readonly
BlankNode
.
The
nominalValue
must
not
be
relied
upon
in
any
way
between
two
separate
processing
runs
of
the
same
document.
Developers
and
authors
must
not
assume
that
the
nominalValue
of
a
The
BlankNode
will
remain
the
same
between
two
processing
runs.
BlankNode
nominalValues
are
only
valid
for
the
most
recent
processing
run
on
the
document.
BlankNode
s
nominalValues
will
often
be
generated
differently
by
different
processors.
Implementers
must
ensure
that
BlankNode
nominalValues
are
unique
within
the
current
environment,
two
BlankNode
s
are
considered
equal
if,
and
only
if,
their
nominalValues
are
strictly
equal.
LiteralNodes
represent
values
such
as
numbers,
dates
and
strings
in
RDF
data.
A
LiteralNode
is
comprised
of
three
attributes:
nominalValue
language
associated
represented
by
a
string
token
datatype
specified
by
a
NamedNode
LiteralNodes
representing
plain
text
in
a
natural
language
may
have
a
language
attribute
specified
by
a
text
string
token,
as
specified
in
[
BCP47
],
normalized
to
lowercase
(e.g.,
'en'
,
'fr'
,
'en-gb'
).
They
may
also
have
a
datatype
attribute
such
as
xsd:string
.
LiteralNodes
representing
values
with
a
specific
datatype,
such
as
the
object
integer
72,
may
have
a
datatype
attribute
specified
in
BCP47
format.
the
form
of
a
NamedNode
(e.g.,
<http://www.w3.org/2001/XMLSchema#integer>
).
[NoInterfaceObject]
interface LiteralNode : Node
{
readonly attribute DOMString nominalValue; readonly attribute DOMString? language; readonly attribute NamedNode
? datatype;
};
datatype
of
type
NamedNode
,
readonly,
nullable
language
of
type
nominalValue
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.
JSON-LD specifies a number of syntax tokens and keyword s that are using in all algorithms described in this section:
@context
@id
@language
@type
@value
@container
@list
@set
@graph
:
@default
@explicit
@omitDefault
@embed
@null
All JSON-LD tokens and keywords are case-sensitive.
@context
keyword
.
Processing of JSON-LD data structure is managed recursively. During processing, each rule is applied using information provided by the active context . Processing begins by pushing a new processor state onto the processor state stack and initializing the active context with the initial context . If a local context is encountered, information from the local context is merged into the active context .
The
active
context
is
used
for
expanding
keys
properties
and
values
of
a
JSON
object
(or
elements
of
a
list
(see
List
Processing
))
using
a
term
mapping
.
It
is
also
used
to
maintain
coercion
mapping
s
from
IRIs
associated
with
terms
to
datatypes,
language
mapping
s
from
terms
to
language
codes,
and
list
mapping
s
and
set
mapping
s
for
IRIs
associated
with
terms.
Processors
must
use
the
lexical
form
of
the
property
when
creating
a
mapping,
as
lookup
is
performed
on
lexical
representations,
not
expanded
IRI
representations.
A
local
context
is
identified
within
a
JSON
object
having
a
key
of
@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
@language
@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
,
@id
@type
@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
@list
@container
true
@list
or
false
@set
.
Merge
the
list
mapping
or
set
mapping
into
the
local
context
@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
prefix:suffix
compact
IRI
and
an
absolute
IRI
,
,
as
a
prefix
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
3.2
2.3.2
until
no
changes
are
made,
mappings
to
IRIs
created
using
an
undefined
term
prefix
will
eventually
resolve
to
absolute
IRIs.
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
.
IRIs
IRI
s
may
be
represented
as
an
absolute
IRI
,
,
a
term
or
a
prefix
:suffix
construct.
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.
IRIs
.
It
was
determined
that
this
added
too
much
complexity,
but
the
issue
can
be
re-examined
in
the
future
based
on
community
input.
Some
keys
and
values
are
expressed
using
IRIs.
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
local
active
context
.
using
an
optional
value
.
The
algorithm
for
generating
a
compacted
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
0
:
container
set
to
@set
,
then
add
1
to
rank
.
@list
and
list
container
is
false
and
term
has
a
container
set
to
@list
,
then
set
list
container
to
true
,
clear
terms
,
set
highest
rank
to
rank
,
and
add
term
to
terms
.
When
selecting
among
multiple
possible
terms
for
a
given
property,
it
may
be
that
multiple
terms
are
defined
with
the
same
IRI
,
but
differ
in
@type
,
@container
or
@language
.
The
purpose
of
this
algorithm
is
to
take
an
term
and
a
value
and
give
it
a
term
rank
.
The
selection
can
then
be
based,
partly,
on
the
entire
term
having
the
highest
term
rank
.
Given a term term , value , and active context determine the term rank using the following steps:
3
.
@list
:
@type
coercion
to
xsd:boolean
,
xsd:integer
,
or
xsd:double
respectively,
term
rank
is
3
,
otherwise
if
term
has
no
@type
or
@language
it
is
2
,
otherwise
1
.
@language
.
If
term
has
@language
null
,
or
term
has
no
@type
or
@language
and
the
active
context
has
no
@language
,
term
rank
is
3
,
otherwise
0
.
@value
.
@value
property,
it
must
have
either
a
@type
or
a
@language
:
@type
property
matching
a
@type
coercion
for
term
,
term
rank
is
3
,
otherwise
if
term
has
no
@type
coersion
and
no
@language
,
term
rank
is
1
,
otherwise
0
.
@language
property
matching
a
@language
definition
for
term
(or
term
has
no
@type
or
@language
definition
and
@language
in
the
active
context
matches
the
value
@language
),
term
rank
is
3
,
otherwise
if
term
has
no
@type
coersion
and
no
@language
,
term
rank
is
1
,
otherwise
0
.
@type
coerced
to
@id
,
term
rank
is
3
,
otherwise
if
term
has
no
@type
coersion
and
no
@language
,
term
rank
is
1
,
otherwise
0
.Some values in JSON-LD can be expressed in a compact form. These values are required to be expanded at times when processing JSON-LD documents.
The algorithm for expanding a value takes an active property and active context . It is implemented as follows:
xsd:integer
or
xsd:double
,
expand
the
value
@value
and
the
string
representation
of
value
@type>
,
@type
and
the
associated
coercion
datatype
expanded
@graph
,
or
the
target
of
an
@id
coercion,
expand
the
value
@id
and
the
value
is
the
expanded
IRI
according
to
the
IRI
Expansion
rules.
@value
and
the
unexpanded
@type
and
the
associated
coercion
datatype
expanded
according
to
the
IRI
Expansion
rules.
@value
and
the
unexpanded
@language
and
value
of
Some values, such as IRIs and typed literals, may be expressed in an expanded form in JSON-LD. These values are required to be compacted at times when processing JSON-LD documents.
The algorithm for compacting an expanded value value takes an active property and active context . It is implemented as follows:
@value
value.
@graph
,
the
compacted
value
is
the
value
associated
with
the
@id
key,
processed
according
to
the
IRI
Compaction
steps.
@id
,
the
compacted
value
is
the
value
associated
with
the
@id
key,
processed
according
to
the
IRI
Compaction
steps.
@value
key.
@id
key,
the
compacted
value
is
value
with
the
value
of
@id
processed
according
to
the
IRI
Compaction
steps.
@language
,
which
matches
the
@language
of
the
value,
or
the
value
has
only
a
@value
key,
the
compacted
value
is
the
value
associated
with
the
@value
key.
@type
key,
the
compacted
value
is
value
with
the
@type
value
processed
according
to
the
IRI
Compaction
steps.
This algorithm is used by the Framing Algorithm and Convert From RDF Algorithm to deterministicly name blank node identifiers. It uses a identifier map and prefix and takes a possibly null identifier and returns a new identifier based on prefix .
The
variable
next
identifier
is
initialized
to
prefix
appended
with
0
.
Expansion
is
the
process
of
taking
a
JSON-LD
document
and
applying
a
context
such
that
all
IRI
,
datatypes,
and
literal
values
are
expanded
so
that
the
context
is
no
longer
necessary.
JSON-LD
document
expansion
is
typically
used
as
a
part
of
Framing
or
Normalization
.
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
a
an
value
element
to
be
expanded.
To
begin,
the
active
context
is
set
to
the
initial
context
,
active
property
is
set
to
nil,
null
,
and
value
element
is
set
to
the
JSON-LD
input
.
@container
set
to
@list
and
any
entry
in
element
is
an
array
,
or
is
a
JSON
object
containing
a
@list
property,
throw
an
exception,
as
lists
of
lists
are
not
allowed.
If
the
expanded
entry
is
null,
drop
it.
If
it's
an
array,
merge
it's
entries
with
element
's
entries.
@context
property,
update
the
active
context
according
to
the
steps
outlined
in
@context
property.
@id
or
@value
,
continue
with
the
next
property
from
element
.
@type
@id
@value
,
the
@type
:
@id
.
@list
@value
or
@language
@list
,
@set
,
or
@graph
,
expand
value
recursively
using
this
algorithm,
passing
copies
of
the
active
context
and
active
property
@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
@list
property
whose
value
is
set
to
value
(unless
value
is
already
in
that
form).
@id
,
@type
,
@value
,
or
@language
.
@value
property
@type
property
and
it's
value
is
not
in
the
@set
or
@list
property,
it
must
be
the
@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:
{"name": "http://xmlns.com/foaf/0.1/name", "homepage": { "@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id""@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
two
three
input
variables:
an
active
context
,
an
active
property
,
and
a
an
value
element
to
be
expanded.
compacted.
To
begin,
the
active
context
is
set
to
the
result
of
performing
Context
Processing
on
the
passed
context
,
active
property
is
set
to
nil,
null
,
and
value
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.
The
active
context
to
the
given
context.
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
If,
after
the
algorithm
outlined
above
is
run,
the
resulting
element
is
an
array
,
put
element
into
the
@graph
property
of
a
new
JSON
object
and
then
set
element
to
that
JSON
object
.
Finally,
add
a
@context
property
to
element
and
set
it
to
the
initially
passed
context
.
JSON-LD Framing allows developers to query by example and force a specific tree layout to a JSON-LD document.
A JSON-LD document is a representation of a directed graph. A single directed graph can have many different serializations, each expressing exactly the same information. Developers typically work with trees, represented as JSON object s. While mapping a graph to a tree can be done, the layout of the end result must be specified in advance. A Frame can be used by a developer on a JSON-LD document to specify a deterministic layout for a graph.
Framing is the process of taking a JSON-LD document, which expresses a graph of information, and applying a specific graph layout (called a Frame ).
The
JSON-LD
document
below
expresses
a
library,
a
book
and
a
chapter:
{
"@context": {
"Book": "http://example.org/vocab#Book",
"Chapter": "http://example.org/vocab#Chapter",
"contains": {
"@id": "http://example.org/vocab#contains",
"@type": "@id"
},
"creator": "http://purl.org/dc/terms/creator",
"description": "http://purl.org/dc/terms/description",
"Library": "http://example.org/vocab#Library",
"title": "http://purl.org/dc/terms/title"
},
"@id":
[{
"@id": "http://example.com/library",
"@type": "Library",
"contains": "http://example.org/library/the-republic"
},
{
"@id": "http://example.org/library/the-republic",
"@type": "Book",
"creator": "Plato",
"title": "The Republic",
"contains": "http://example.org/library/the-republic#introduction"
},
{
"@id": "http://example.org/library/the-republic#introduction",
"@type": "Chapter",
"description": "An introductory chapter on The Republic.",
"title": "The Introduction"
}]
}
Developers
typically
like
to
operate
on
items
in
a
hierarchical,
tree-based
fashion.
Ideally,
a
developer
would
want
the
data
above
sorted
into
top-level
libraries,
then
the
books
that
are
contained
in
each
library,
and
then
the
chapters
contained
in
each
book.
To
achieve
that
layout,
the
developer
can
define
the
following
frame
:
{
"@context": {
"Book": "http://example.org/vocab#Book",
"Chapter": "http://example.org/vocab#Chapter",
"contains": "http://example.org/vocab#contains",
"creator": "http://purl.org/dc/terms/creator"
"description": "http://purl.org/dc/terms/description"
"Library": "http://example.org/vocab#Library",
"title": "http://purl.org/dc/terms/title"
},
"@type": "Library",
"contains": {
"@type": "Book",
"contains": {
"@type": "Chapter"
}
}
}
When
Framing
makes
use
of
the
framing
Subject
Flattening
algorithm
is
run
against
the
previously
to
place
each
object
defined
JSON-LD
document,
paired
with
the
frame
above,
in
the
following
JSON-LD
document
is
into
a
flat
list
of
objects,
allowing
them
to
be
operated
upon
by
the
end
result:
framing
algorithm.
@id
to
a
parent
JSON
object
and
property
or
parent
array.
This algorithm is a work in progress. Presently, it only works for documents without named graphs.
The
framing
algorithm
takes
an
JSON-LD
input
that
has
been
normalized
according
to
the
Normalization
Algorithm
(
normalized
expanded
input
),
)
and
an
input
frame
(
expanded
frame
)
that
has
have
been
expanded
according
to
the
Expansion
Algorithm
(
expanded
frame
),
,
and
a
number
of
options
and
produces
JSON-LD
output
.
The
following
series
of
steps
is
the
recursive
portion
of
the
framing
algorithm:
Create
framing
context
by
setting
using
null
for
the
map
of
embeds
,
the
object
embed
flag
set
to
true
,
clearing
the
explicit
inclusion
flag
set
to
false
,
and
clearing
the
omit
missing
properties
default
flag
.
Override
these
values
based
on
input
options
provided
set
to
the
algorithm
by
the
application.
Generate
a
list
false
along
with
map
of
frames
by
processing
the
expanded
frame
:
If
the
expanded
frame
is
not
an
array
,
set
match
limit
flattened
subjects
set
to
1,
place
the
expanded
frame
into
the
list
result
of
frames
,
and
set
the
JSON-LD
output
performing
Subject
Flattening
to
null
.
If
the
on
expanded
frame
is
input
.
Also
create
results
as
an
empty
array
,
place
an
empty
object
into
the
list
of
frames
,
set
.
Invoke
the
JSON-LD
output
to
an
array
,
and
set
match
limit
recursive
algorithm
using
framing
context
to
-1.
If
(
state
),
the
map
of
flattened
subjects
(
subjects
),
expanded
frame
is
a
non-empty
array
,
add
each
item
in
the
expanded
(
frame
into
),
result
as
parent
,
and
null
as
active
property
.
The
following
series
of
steps
is
the
list
recursive
portion
of
frames
,
set
the
JSON-LD
output
to
an
array
,
and
set
match
limit
to
-1.
framing
algorithm:
Invalid
Frame
Format
@type
rdf:type
@type
rdf:type
s.
Note:
the
rdf:type
@type
rdf:type
@type
property,
@embed
@explicit
using
the
current
values
for
object
embed
flag
true
.
@id
and
id
.
@id
@list
,
then
@id
@list
and
the
value
@list
array
as
follows:
@id
@list
as
active
property
.
null
@list
@id
of
item
as
the
key
true
@omitDefault
which
is
true
or
if
it
does
not
contain
false
,
set
@omitDefault
but
the
@preserve
and
a
value
that
is
@default
@default
.
@null
otherwise.
At the completion of the recursive algorithm, results will contain the top-level subject definition s.
The
final,
non-recursive
step
final
two
steps
of
the
framing
algorithm
requires
the
JSON-LD
output
require
results
to
be
compacted
according
to
the
Compaction
Algorithm
by
using
the
context
provided
in
the
input
frame
.
The
resulting
value
is
the
final
output
of
If
the
frame
has
no
context,
compaction
algorithm
and
is
what
should
be
returned
to
performed
with
an
empty
context
(not
a
null
context).
The
compaction
result
must
use
the
application.
What
are
@graph
keyword
at
the
implications
for
framing
lists?
3.11
Normalization
This
algorithm
is
a
work
in
progress,
do
not
implement
it.
Normalization
is
top-level,
even
if
the
process
of
taking
JSON-LD
input
and
performing
a
deterministic
transformation
on
that
input
that
results
in
a
normalized
and
serialized
JSON-LD
representation.
Normalization
context
is
achieved
by
transforming
JSON-LD
input
empty
or
if
there
is
only
one
element
to
RDF,
as
described
put
in
RDF
Conversion
,
invoking
the
normalization
procedure
as
described
in
[
RDF-NORMALIZATION
],
returning
@graph
array.
Subsequently,
replace
all
key-value
pairs
where
the
serialized
results.
There
an
open
issue
(
ISSUE-53
)
on
key
is
@preserve
with
the
purpose
and
results
of
performing
normalization.
Previous
versions
of
value
from
the
specification
generated
JSON-LD
as
key-pair.
If
the
result
of
value
from
the
normalization
algorithm,
however
normalization
is
a
process
required
across
different
linked
data
serializations.
To
be
useful,
a
graph
requires
an
identical
normalized
representation
that
key-pair
is
independent
of
the
data
format
originally
used
for
markup,
or
the
way
in
which
language
features
or
publisher
preferences
create
differences
in
@null
,
replace
the
markup
of
identical
graphs.
It
may
be
that
value
with
null
.
If,
after
replacement,
an
array
contains
only
the
need
for
either
or
both
of
flattening
algorithm
or
to
retrieve
such
a
cryptographic
signature.
Normalization
is
useful
when
comparing
two
graphs
against
one
another,
when
generating
a
detailed
list
of
differences
between
two
graphs,
and
when
generating
a
cryptographic
digital
signature
for
information
contained
in
a
graph
or
when
generating
a
hash
of
value
null
remove
the
information
contained
in
a
graph.
The
example
below
is
value,
leaving
an
un-normalized
JSON-LD
document:
{
"@context": {
"name": "http://xmlns.com/foaf/0.1/name",
"homepage": {
"@id": "http://xmlns.com/foaf/0.1/homepage",
"@type": "@id"
},
"xsd": "http://www.w3.org/2001/XMLSchema#"
},
"name": "Manu Sporny",
"homepage": "http://manu.sporny.org/"
}
empty
array.
The
example
below
resulting
value
is
the
normalized
form
of
the
final
JSON-LD
document
above:
output
.
The
normalization
algorithm
for
JSON-LD
removes
all
unnecessary
whitespace
in
the
fully
normalized
form.
Not
clear
that
whitespace
must
be
normalized,
as
the
JSON-LD
representation
can't
be
used
directly
needs
to
create
a
signature,
but
would
be
based
on
updated
to
consider
@graph
.
For
1.0,
this
might
not
require
anything,
as
the
serialized
result
default
implementation
of
[
RDF-NORMALIZATION
Subject
Flattening
].
should
flatten
everything
into
a
single
graph.
Notice
how
all
of
the
term
s
have
been
Subject
Flattening
takes
as
input
an
expanded
JSON-LD
document,
and
sorted
results
in
alphabetical
order.
Also,
notice
how
the
subject
a
JSON
object
has
been
labeled
subjects
with
a
named
mapping
from
each
object
represented
in
the
document
to
a
single
entry
within
the
input
document,
assigning
blank
node
.
Normalization
ensures
that
any
arbitrary
graph
containing
exactly
the
same
information
would
be
normalized
identifiers
to
exactly
the
same
form
shown
above.
objects
without
a
@id,
or
with
an
@id
that
references
a
blank
node
identifier.
The
normalization
algorithm
transforms
operates
on
the
JSON-LD
input
into
RDF,
normalizes
it
according
to
[
RDF-NORMALIZATION
]
initially
empty
subjects
and
then
transforms
back
to
JSON-LD.
The
result
takes
as
input
the
current
document
element
.
@id
set
to
@id
:
property
and
http://www.w3.org/1999/02/22-rdf-syntax-ns#first
,
let
object
representation
be
object
represented
in
expanded
form
as
described
in
Value
Expansion
.
Set
value
as
the
last
entry
in
array
.
to
subject
.
@list.
Create
a
new
JSON
object
@list
and
an
array
The
algorithm
states
to
set
the
last
entry
property
in
array
subject
is
not
using
the
mapped
values,
but
it
really
should
merge,
if
the
property
already
exists
in
subject
.
The
algorithm
should
descend
into
@graph
and
create
a
JSON
Object
with
parallel
flattened
structure
of
subject
to
object
within
that
@graph
representation.
Recursive
@graph
definitions
are
also
flattened
into
the
default
graph.
The
algorithm
should
also
take
an
option
which
descends
into
@id
@graph
having
and
flattens
all
definitions
at
the
same
level,
effectively
flatting
default
and
named
graphs
into
a
value
of
single
default
graph;
this
should
be
the
default
implementation
for
1.0.
This
algorithm
replaces
an
already
embedded
subject
:
Create
a
new
JSON
Object
definition
with
key/value
pair
of
@id
and
a
string
representation
subject
reference
.
It
then
recursively
removes
any
entries
in
the
map
of
embeds
that
had
the
removed
subject
and
use
definition
in
their
parent
chain.
The
algorithm
is
invoked
with
a
framing
context
and
subject
id
value
id
.
@type
,
replace
@id
of
id
,
removing
that
@id
in
their
parent
chain.
This
algorithm
recursively
embeds
property
values
in
subject
definition
output
,
given
a
string
representation
of
framing
context
,
input
subject
definition
object
element
,
active
property
,
and
output
.
@list
,
then
create
a
new
@type
@list
and
@list
as
active
property
,
and
the
new
array
as
output
.
Continue
to
the
next
item
.
@id
of
When
normalizing
coercing
numbers
to
xsd:integer
or
xsd:double
values,
as
it,
e.g.,
happens
during
RDF
Conversion
,
implementers
must
ensure
that
the
normalized
value
result
is
a
string.
In
order
to
generate
canonical
lexical
representation
in
the
form
of
a
string
.
A
canonical
lexical
representation
is
a
set
of
literals
from
among
the
valid
set
of
literals
for
a
datatype
such
that
there
is
a
one-to-one
mapping
between
the
canonical
lexical
representation
and
a
value
in
the
value
space
as
defined
in
[
XMLSCHEMA-2
].
In
other
words,
every
value
must
be
converted
to
a
deterministic
string
representation.
The
canonical
lexical
representation
of
an
integer
,
i.e.,
a
number
without
fractions
or
a
number
coerced
to
xsd:integer
,
is
a
finite-length
sequence
of
decimal
digits
(
0-9
)
with
an
optional
leading
minus
sign;
leading
zeroes
are
prohibited.
To
convert
the
number
in
JavaScript,
implementers
can
use
the
following
snippet
of
code:
(value).toFixed(0).toString()
The
canonical
lexical
representation
of
a
double
value,
output
equivalent
,
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
(
printf("%1.6e",
value)
+
function
)
are
prohibited
in
C
the
exponent.
If
the
exponent
is
zero,
it
must
be
used
where
"%1.6e"
indicated
by
E0
.
For
the
mantissa,
the
preceding
optional
plus
sign
is
prohibited
and
the
string
formatter
decimal
point
is
required.
Leading
and
value
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
value
left
of
the
decimal
point
and
at
least
a
single
digit
to
be
converted.
the
right
of
the
decimal
point
unless
the
value
being
represented
is
zero.
The
canonical
representation
for
zero
is
0.0E0
.
To
convert
the
a
double
value
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
needs
such
as
decimals
need
to
be
normalized,
JSON-LD
authors
should
not
use
values
that
are
going
to
undergo
automatic
conversion.
This
is
due
to
the
lossy
nature
of
xsd:double
values.
Authors
should
instead
use
the
expanded
object
form
to
set
the
canonical
lexical
representation
directly.
When JSON-native datatypes, like 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,
backslash-escapes
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
in
some
versions
of
PHP.
when
generating
a
byte
stream
for
processes
such
as
normalization.
other
JSON
parsers
might
not
understand
those
escaping
characters.
There
is
no
need
to
backslash-escape
forward-slashes
forward
slashes
in
JSON-LD.
To
aid
interoperability
between
JSON-LD
processors,
a
JSON-LD
serializer
must
not
backslash-escape
forward
slashes.
A
JSON-LD
document
may
be
converted
to
any
between
other
RDF-compatible
document
format
formats
using
the
algorithm
algorithms
specified
in
this
section.
The
JSON-LD
Processing
Model
describes
processing
rules
for
extracting
RDF
from
a
JSON-LD
document.
document,
and
for
transforming
an
array
of
Statement
retrieved
by
processing
another
serialization
format
into
JSON-LD.
Note
that
many
uses
of
JSON-LD
may
not
require
generation
of
RDF.
The
processing
algorithm
algorithms
described
in
this
section
is
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
triples
statements
during
the
output
process
and
are
not
required
to
implement
the
algorithm
exactly
as
described.
This section is non-normative.
JSON-LD is intended to have an easy to parse grammar that closely models existing practice in using JSON for describing object representations. This allows the use of existing libraries for parsing JSON.
As
with
other
grammars
used
for
describing
Linked
Data
,
a
key
concept
is
that
of
a
resource
.
Resources
may
be
of
three
basic
types:
IRI
NamedNode
s,
,
representing
IRIs
for
describing
externally
named
entities,
BNodes
,
BlankNode
,
resources
for
which
an
external
name
does
not
exist,
or
is
not
known,
and
Literals,
LiteralNode
,
which
describe
terminal
entities
such
as
strings,
dates
and
other
representations
having
a
lexical
representation
possibly
including
an
explicit
language
or
datatype.
An Internationalized Resource Identifier ( IRI ), as described in [ RFC3987 ], is a mechanism for representing unique identifiers on the web. In Linked Data , an IRI is commonly used for expressing a subject , a property or an object .
Data described with JSON-LD may be considered to be the representation of a graph made up of subject and object resource s related via a property resource . However, specific implementations may choose to operate on the document as a normal JSON description of objects having attributes.
The algorithm below is designed for in-memory implementations with random access to JSON object elements.
A
conforming
JSON-LD
processor
implementing
RDF
conversion
must
implement
a
processing
algorithm
that
results
in
the
same
default
graph
set
of
RDF
Statement
s
that
the
following
algorithm
generates:
The
algorithm
takes
five
input
variables:
a
new
processor
state
with
with
the
active
context
set
element
to
the
initial
context
and
be
converted,
an
active
subject
,
active
property
and
graph
name
.
To
begin,
the
active
subject
,
active
property
initialized
and
graph
name
are
set
to
NULL.
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
@type
@type
.
@language
@list
Statement
representing
@id
property,
the
@id
@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
xsd:integer
or
xsd:double
,
depending
on
if
the
value
contains
a
fractional
and/or
an
exponential
component.
xsd:boolean
.
Statement
using
active
subject
,
active
property
,
active
object
and
graph
name
.
List
Conversion
is
the
process
of
taking
an
array
of
values
and
adding
them
to
a
newly
created
RDF
Collection
(see
[
RDF-SCHEMA
])
by
linking
each
element
of
the
list
using
rdf:first
and
rdf:next
,
terminating
the
list
with
rdf:nil
using
the
following
sequence:
The
algorithm
is
invoked
with
an
array
array
,
the
active
property
,
and
the
active
context
and
returns
a
value
to
be
used
as
an
active
object
.
in
the
calling
location.
rdf:nil
.
Statement
using
using
the
active
subject
,
active
property
and
a
newly
generated
rdf:first
as
the
active
property
.
rdf:nil
.
Statement
using
first
blank
node
,
rdf:rest
and
rest
blank
node
.
In
some
cases,
data
exists
natively
in
Triples
or
Quads
form;
for
example,
if
the
data
was
originally
represented
in
an
RDF
graph
or
triple/quad
store.
This
algorithm
is
designed
to
simply
translate
an
array
of
Statement
s
into
a
JSON-LD
document.
The
conversion
algorithm
takes
a
single
parameter
input
in
the
form
of
an
array
of
Statement
representations.
rdf:first
.
rdf:rest
.
rdf:first
,
create
a
new
entry
in
listMap
with
for
name
and
subject
and
an
array
value
containing
object
representation
and
skip
to
the
next
statement.
rdf:rest
,
and
object
is
a
BlankNode
,
create
a
new
entry
in
restMap
to
map
name
and
subject
to
a
value
being
the
result
of
IRI
expansion
on
object
and
skip
to
the
next
statement.
@id
and
a
string
representation
of
name
and
use
as
value
.
@graph
,
initialize
it
as
a
new
array
ary
.
name
and
subject
:
@id
and
a
string
representation
of
subject
and
use
as
value
.
@id
and
a
string
representation
of
subject
and
use
as
value
.
rdf:type
:
@type
,
creating
an
entry
in
value
if
necessary.
rdf:nil
:
@list
representation:
{"@list":
[]}
.This section is non-normative.
This section is included merely for standards community review and will be submitted to the Internet Engineering Steering Group if this specification becomes a W3C Recommendation.
application/json
MIME
media
type.
eval()
function.
It
is
recommended
that
a
conforming
parser
does
not
attempt
to
directly
evaluate
the
JSON-LD
frame
and
instead
purely
parse
the
input
into
a
language-native
data
structure.
The initial context is defined with the following default entries:
{ "@context": { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": { "@type": "@id"} } }
Processors must act as if the initial context is defined in the outer-most level when processing JSON-LD documents.
Should we define other default prefixes?
The editors would like to thank Mark Birbeck, who provided a great deal of the initial push behind the JSON-LD work via his work on RDFj, Dave Lehn and Mike Johnson who reviewed, provided feedback, and performed several implementations of the specification, and Ian Davis, who created RDF/JSON. Thanks also to Nathan Rixham, Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant, Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Niklas Lindström, Markus Lanthaler, and Richard Cyganiak for their input on the specification.