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
"Web
of
Knowledge".
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. 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:
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 {
object expand (object input, optional object? context) raises (InvalidContext);
object compact (object input, optional object? context) raises (InvalidContext, ProcessingError);
object frame (object input, object frame, object options) raises (InvalidFrame);
DOMString normalize (object input, optional object? context) raises (InvalidContext);
void triples (object input, JsonLdTripleCallback
tripleCallback, optional object? context) raises (InvalidContext);
};
compact
input
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
|
|
|
The JSON-LD object to perform compaction on. |
context |
object
|
|
|
The
base
context
to
use
when
compacting
the
input
.
|
Exception | Description | ||||
---|---|---|---|---|---|
InvalidContext |
|
||||
ProcessingError |
|
object
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
|
|
|
The JSON-LD object to copy and perform the expansion upon. |
context |
object
|
|
|
An
external
context
to
use
additionally
to
the
context
embedded
in
input
when
expanding
the
input
.
|
Exception | Description | ||||
---|---|---|---|---|---|
InvalidContext |
|
object
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
|
|
|
The JSON-LD object to perform framing on. |
frame |
object
|
|
|
The frame to use when re-arranging the data. |
options |
object
|
|
|
A set of options that will affect the framing algorithm. |
Exception | Description | ||||
---|---|---|---|---|---|
InvalidFrame |
|
object
normalize
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
must
be
returned.
The
output
is
the
serialized
representation
returned
from
the
Normalization
Algorithm
.
It's
still
an
open
question
if
the
result
is
a
DOMString
representing
the
serialized
graph
in
JSON-LD,
or
an
array
representation
which
is
in
normalized
form.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
|
|
|
The JSON-LD object to perform normalization upon. |
context |
object
|
|
|
An
external
context
to
use
additionally
to
the
context
embedded
in
input
when
expanding
the
input
.
|
Exception | Description | ||||
---|---|---|---|---|---|
InvalidContext |
|
object
DOMString
triples
input
according
to
the
RDF
Conversion
Algorithm
,
calling
the
provided
tripleCallback
for
each
triple
generated.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
input |
object
|
|
|
The JSON-LD object to process when outputting triples. |
tripleCallback |
|
|
|
A
callback
that
is
called
whenever
a
processing
error
occurs
on
the
given
input
.
This
callback
should
be
aligned
with
the
RDF
API.
|
context |
object
|
|
|
An
external
context
to
use
additionally
to
the
context
embedded
in
input
when
expanding
the
input
.
|
Exception | Description | ||||
---|---|---|---|---|---|
InvalidContext |
|
object
void
The
JsonLdTripleCallback
is
called
whenever
the
processor
generates
a
triple
during
the
triple()
call.
[NoInterfaceObject Callback]
interface JsonLdTripleCallback {
void triple (DOMString subject, DOMString property, DOMString objectType, DOMString object, DOMString? datatype, DOMString? language);
};
triple
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
subject |
DOMString
|
|
|
The subject IRI that is associated with the triple. |
property |
DOMString
|
|
|
The property IRI that is associated with the triple. |
objectType |
DOMString
|
|
|
The
type
of
object
that
is
associated
with
the
triple.
Valid
values
are
IRI
and
literal
.
|
object |
DOMString
|
|
|
The object value associated with the subject and the property. |
datatype |
DOMString
|
|
|
The datatype associated with the object. |
language |
DOMString
|
|
|
The language associated with the object in BCP47 format. |
void
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
keywords
keyword
s
that
are
using
in
all
algorithms
described
in
this
section:
@context
@base
@id
@vocab
@language
@language
@type
@datatype
@value
:
All JSON-LD tokens and keywords are case-sensitive.
@context
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
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,
and
list
mapping
s
for
IRIs
associated
with
terms.
A
local
context
is
identified
within
a
JSON
object
having
a
key
of
@context
with
string
,
array
or
a
JSON
object
value.
When
processing
a
local
context
,
special
processing
rules
apply:
@context
@context
element
using
the
JSON
Pointer
@base
@language
key,
it
must
have
a
value
of
a
simple
string
null
.
Add
the
@coerce
@id
@language
@type
key,
null
@id
.
@id
,
merge
into
the
local
context
coercion
mapping
.
@list
key,
the
true
or
false
.
Merge
It
can
be
difficult
to
distinguish
between
a
single
prefix:suffix
value,
a
single
term
value
or
an
array
of
prefix:suffix
or
term
values.
When
merging
with
an
existing
mapping
in
the
active
context
,
map
all
term
values
to
array
form
and
replace
with
the
union
of
the
value
from
the
local
context
and
the
value
of
the
active
context
.
If
the
result
is
an
array
with
a
single
value,
the
processor
may
represent
this
as
a
string
value.
Initial
Context
The
initial
context
is
initialized
absolute
IRI
,
as
follows:
@base
is
set
using
section
5.1
Establishing
a
Base
URI
of
[
RFC3986
prefix
].
Processors
may
provide
seem
to
be
a
means
of
setting
the
base
valid
IRI
programatically.
@coerce
is
set
with
scheme
.
When
performing
repeated
IRI
expansion,
a
single
term
used
as
a
prefix
may
not
have
a
valid
mapping
from
@iri
due
to
@type
.
dependencies
in
resolving
term
definitions.
By
continuing
Step
3.2
until
no
changes
are
made,
mappings
to
IRIs
created
using
an
undefined
term
prefix
will
eventually
resolve
to
absolute
IRIs.
{
"@base": ,
"@coerce": {
"@iri": "@type"
}
}
Issue
43
concerns
performing
IRI
expansion
in
the
key
position
of
a
context
definition.
Keys
and
some
values
are
evaluated
to
produce
an
IRI.
IRI
.
This
section
defines
an
algorithm
for
transforming
a
value
representing
an
IRI
into
an
actual
IRI.
IRI
.
IRIs
may
be
represented
as
an
absolute
IRI,
IRI
,
a
term
,
or
a
prefix
:suffix
construct,
or
as
a
value
relative
to
@base
or
@vocab
.
construct.
The algorithm for generating an IRI is:
Previous
versions
of
this
specification
used
@coerce
@base
mapping)
and
the
active
context
has
a
@vocab
mapping,
join
the
mapped
value
to
the
suffix
using
textual
concatenation.
If
the
define
IRI
being
processed
is
for
a
subject
or
object
(i.e.,
not
a
property)
and
the
active
context
has
a
@base
mapping,
join
the
mapped
value
prefixes
used
to
resolve
relative
IRIs.
It
was
determined
that
this
added
too
much
complexity,
but
the
suffix
using
the
method
described
issue
can
be
re-examined
in
[
RFC3986
].
Otherwise,
use
the
value
directly
as
an
IRI.
future
based
on
community
input.
Some keys and values are expressed using IRIs. This section defines an algorithm for transforming an IRI to a compact IRI using the term s specified in the local context .
The algorithm for generating a compacted IRI is:
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
is:
takes
an
active
property
and
active
context
.
It
is
implemented
as
follows:
@value
and
the
@type>
,
and
the
xsd:boolean
,
xsd:integer
,
or
xsd:double
,
depending
on
value
.
@iri
,
@id
coercion,
expand
the
value
by
adding
a
new
key-value
pair
where
the
key
is
@iri
@id
and
the
value
is
the
expanded
IRI
according
to
the
IRI
Expansion
rules.
@literal
@value
and
the
unexpanded
value.
The
second
key-value
pair
will
be
@datatype
@type
and
the
associated
coercion
datatype
expanded
according
to
the
IRI
Expansion
rules.
@language
,
expand
value
by
adding
two
new
key-value
pairs.
The
first
key-value
pair
will
be
@value
and
the
unexpanded
value.
The
second
key-value
pair
will
be
@language
and
value
of
@language
from
the
active
context
.Some values, such as IRIs and typed literals, may be expressed in an expanded form in JSON-LD. These values are required to be compacted at times when processing JSON-LD documents.
The
algorithm
for
compacting
a
an
expanded
value
is:
value
takes
an
active
property
and
active
context
.
It
is
implemented
as
follows:
@value
value.
@iri
@id
,
the
compacted
value
is
the
value
associated
with
the
@iri
@id
key,
processed
according
to
the
IRI
Compaction
steps.
@literal
@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,
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
is
takes
three
input
variables:
an
active
context
,
an
active
property
,
and
a
work
in
progress,
do
not
implement
it.
If
value
to
be
expanded.
To
begin,
the
top-level
item
in
active
context
is
set
to
the
initial
context
,
active
property
is
set
to
nil,
and
value
is
set
to
the
JSON-LD
input
.
@id
or
@type
and
the
value
is
a
string
,
expand
the
value
according
to
IRI
Expansion
.
@value
,
the
value
must
be
a
string
and
is
not
subject
to
further
expansion.
@list
expansion,
replace
the
value
@list
and
value
set
to
the
current
value.
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" } }
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
is
takes
two
input
variables:
an
active
property
,
and
a
work
in
progress,
do
not
implement
it.
Perform
value
to
be
expanded.
To
begin,
the
active
property
is
set
to
nil,
and
value
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.
Set
the
The
active
context
to
the
given
context.
@id
or
@type
@id
key
or
the
value
contains
a
@value
key,
the
compacted
value
is
the
result
of
performing
Value
Compaction
@list
key,
and
the
active
property
is
subject
to
list
coercion,
the
compacted
value
is
the
result
of
performing
this
algorithm
on
that
value.
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 the framing algorithm is run against the previously defined JSON-LD document, paired with the frame above, the following JSON-LD document is the end result:
{ "@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" }, "@id": "http://example.org/library", "@type": "Library", "contains": { "@id": "http://example.org/library/the-republic", "@type": "Book", "creator": "Plato", "title": "The Republic", "contains": { "@id": "http://example.org/library/the-republic#introduction", "@type": "Chapter", "description": "An introductory chapter on The Republic.", "title": "The Introduction" }, }, }
This algorithm is a work in progress, do not implement it. There was also a recent update to the algorithm in order to auto-embed frame-unspecified data (if the explicit inclusion flag is not set) in order to preserve graph information. This change is particularly important for comparing subgraphs (or verifying digital signatures on subgraphs). This change is not yet reflected in the algorithm below.
The framing algorithm takes JSON-LD input that has been normalized according to the Normalization Algorithm ( normalized input ), an input frame that has 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:
null
.
Invalid
Frame
Format
exception.
Add
each
matching
item
from
the
normalized
input
to
the
matches
array
and
decrement
the
match
limit
by
1
if:
rdf:type
that
exists
in
the
item's
list
of
rdf:type
s.
Note:
the
rdf:type
can
be
an
array
,
but
only
one
value
needs
to
be
in
common
between
the
item
and
the
expanded
frame
for
a
match.
rdf:type
property,
but
every
property
in
the
expanded
frame
exists
in
the
item.
matches array not defined anywhere.
@embed
@explicit
true
or
false
,
set
the
associated
flag
to
true
.
@subject
@id
property,
replace
the
item
with
the
value
of
the
@subject
@id
property.
@subject
@id
property,
and
its
IRI
is
in
the
map
of
embedded
subjects
,
throw
a
Duplicate
Embed
exception.
@subject
@id
property
and
its
IRI
is
not
in
the
map
of
embedded
subjects
:
@subject
@id
.
rdf:type
:
@iri
@id
value
that
exists
in
the
normalized
input
,
replace
the
object
in
the
recursion
input
list
with
a
new
object
containing
the
@subject
@id
key
where
the
value
is
the
value
of
the
@iri
@id
,
and
all
of
the
other
key-value
pairs
for
that
subject.
Set
the
recursion
match
frame
to
the
value
associated
with
the
match
frame
's
key.
Replace
the
value
associated
with
the
key
by
recursively
calling
this
algorithm
using
recursion
input
list
,
recursion
match
frame
as
input.
null
otherwise.
null
,
process
the
omit
missing
properties
flag
:
@omitDefault
true
or
false
,
set
the
associated
flag
to
true
.
@default
keyword
is
set
in
the
property
frame
set
the
item's
value
to
the
value
of
@default
.
null
set
it
to
the
item,
otherwise,
append
the
item
to
the
JSON-LD
output
.
The final, non-recursive step of the framing algorithm requires the JSON-LD output 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 the compaction algorithm and is what should be returned to the application.
What are the implications for framing lists?
This algorithm is a work in progress, do not implement it.
Normalization
is
the
process
of
taking
JSON-LD
input
and
performing
a
deterministic
transformation
on
that
input
that
results
in
all
aspects
of
the
graph
being
fully
expanded
a
normalized
and
named
in
the
serialized
JSON-LD
output
.
The
normalized
output
representation.
Normalization
is
generated
achieved
by
transforming
JSON-LD
input
to
RDF,
as
described
in
such
a
way
that
any
conforming
RDF
Conversion
,
invoking
the
normalization
procedure
as
described
in
[
RDF-NORMALIZATION
],
returning
the
serialized
results.
There
an
open
issue
(
ISSUE-53
)
on
the
purpose
and
results
of
performing
normalization.
Previous
versions
of
the
specification
generated
JSON-LD
processor
will
generate
identical
output
given
as
the
same
input.
The
problem
result
of
the
normalization
algorithm,
however
normalization
is
a
fairly
difficult
technical
problem
to
solve
because
it
requires
a
directed
graph
to
process
required
across
different
linked
data
serializations.
To
be
ordered
into
a
set
of
nodes
and
edges
in
useful,
a
deterministic
way.
This
graph
requires
an
identical
normalized
representation
that
is
easy
to
do
when
all
independent
of
the
nodes
have
unique
names,
but
very
difficult
to
do
when
some
data
format
originally
used
for
markup,
or
the
way
in
which
language
features
or
publisher
preferences
create
differences
in
the
markup
of
identical
graphs.
It
may
be
that
the
nodes
are
not
labeled.
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 the information contained in a graph.
The example below is 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/" }
The example below is the normalized form of the JSON-LD document above:
Whitespace is used below to aid readability. 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 to create a signature, but would be based on the serialized result of [ RDF-NORMALIZATION ].
[{ "@id": "_:c14n0", "http://xmlns.com/foaf/0.1/homepage": { "@id": "http://manu.sporny.org/" }, "http://xmlns.com/foaf/0.1/name": "Manu Sporny" }]
Notice
how
all
of
the
term
s
have
been
expanded
and
sorted
in
alphabetical
order.
Also,
notice
how
the
subject
has
been
labeled
with
a
named
blank
node
identifier
.
.
Normalization
ensures
that
any
arbitrary
graph
containing
exactly
the
same
information
would
be
normalized
to
exactly
the
same
form
shown
above.
The
subject
IRI
is
expressed
using
a
key-value
pair
in
a
JSON
object
where
the
key
is
@subject
and
the
value
is
a
string
that
is
an
IRI
or
a
JSON
object
containing
the
key
@iri
and
a
value
that
is
a
string
that
is
an
IRI.
list
of
expanded
nodes
A
list
of
all
nodes
in
normalization
algorithm
transforms
the
JSON-LD
input
graph
containing
no
embedded
objects
and
having
all
keys
and
values
expanded
according
to
the
steps
in
the
Expansion
Algorithm
.
alpha
and
beta
values
The
words
alpha
and
beta
refer
to
the
first
and
second
nodes
or
values
being
examined
in
an
algorithm.
The
names
are
merely
used
to
refer
to
each
input
value
to
a
comparison
algorithm.
renaming
counter
A
counter
that
is
used
during
the
Node
Relabeling
Algorithm
.
The
counter
typically
starts
at
one
(1)
and
counts
up
for
every
node
that
is
relabeled.
There
will
be
two
such
renaming
counters
in
an
implementation
of
the
normalization
algorithm.
The
first
is
the
labeling
counter
and
the
second
is
the
deterministic
labeling
counter
.
serialization
label
An
identifier
that
is
created
to
aid
in
the
normalization
process
in
the
Deep
Comparison
Algorithm
.
The
value
typically
takes
the
form
of
s<NUMBER>
or
c<NUMBER>
.
3.8.2
Normalization
State
When
performing
the
steps
required
by
the
normalization
algorithm,
it
is
helpful
to
track
the
many
pieces
of
information
in
a
data
structure
called
the
normalization
state
.
Many
of
these
pieces
simply
provide
indexes
into
the
graph.
The
information
contained
in
the
normalization
state
is
described
below.
node
state
Each
node
in
the
graph
will
be
assigned
a
node
state
.
This
state
contains
the
information
necessary
to
deterministically
label
all
nodes
in
the
graph.
A
node
state
includes:
node
reference
A
node
reference
is
a
reference
to
a
node
in
the
graph.
For
a
given
node
state
,
its
node
reference
refers
to
the
node
that
the
state
is
for.
When
a
node
state
is
created,
its
node
reference
should
be
to
the
node
it
is
created
for.
outgoing
list
Lists
the
label
s
for
all
nodes
that
are
properties
of
the
node
reference
.
This
list
should
be
initialized
by
iterating
over
every
object
associated
with
a
property
in
the
node
reference
adding
its
label
if
it
is
another
node.
incoming
list
Lists
the
label
s
for
all
nodes
in
the
graph
for
which
the
node
reference
is
a
property.
This
list
is
initialized
to
an
empty
list.
outgoing
serialization
map
Maps
node
label
s
to
serialization
label
s.
This
map
is
initialized
to
an
empty
map.
When
this
map
is
populated,
RDF,
normalizes
it
will
be
filled
with
keys
that
are
the
label
s
of
every
node
in
the
graph
with
a
label
that
begins
with
_:
and
that
has
a
path,
via
properties,
that
starts
with
the
node
reference
.
outgoing
serialization
A
string
that
can
be
lexicographically
compared
to
the
outgoing
serialization
s
of
other
node
state
s.
It
is
a
representation
of
the
outgoing
serialization
map
and
other
related
information.
This
string
is
initialized
according
to
an
empty
string.
incoming
serialization
map
[
Maps
node
label
s
to
serialization
label
s.
This
map
is
initialized
to
an
empty
map.
When
this
map
is
populated,
it
will
be
filled
with
keys
that
are
the
label
s
of
every
node
in
the
graph
with
a
label
RDF-NORMALIZATION
that
begins
with
_:
and
that
has
a
path,
via
properties,
that
ends
with
the
node
reference
.
incoming
serialization
A
string
that
can
be
lexicographically
compared
to
the
outgoing
serialization
s
of
other
node
state
s.
It
is
a
representation
of
the
incoming
serialization
map
]
and
other
related
information.
This
string
is
initialized
to
an
empty
string.
node
state
map
A
mapping
from
a
node's
label
to
a
node
state
.
It
is
initialized
to
an
empty
map.
labeling
prefix
The
labeling
prefix
is
a
string
that
is
used
as
the
beginning
of
a
node
label
.
It
should
be
initialized
then
transforms
back
to
a
random
base
string
that
starts
with
the
characters
_:
,
is
not
used
by
any
other
node's
label
in
the
JSON-LD
input
,
and
does
not
start
with
the
characters
_:c14n
.
JSON-LD.
The
prefix
has
two
uses.
First
it
is
used
to
temporarily
name
nodes
during
the
normalization
algorithm
in
a
way
that
doesn't
collide
with
the
names
that
already
exist
as
well
as
the
names
that
will
be
generated
by
the
normalization
algorithm.
Second,
it
will
eventually
be
set
to
_:c14n
to
generate
the
final,
deterministic
labels
for
nodes
in
the
graph.
This
prefix
will
be
concatenated
with
the
labeling
counter
to
produce
a
node
label
.
For
example,
_:j8r3k
is
a
proper
initial
value
for
the
labeling
prefix
.
labeling
counter
A
counter
that
is
used
to
label
nodes.
It
is
appended
to
the
labeling
prefix
to
create
a
node
label
.
It
is
initialized
to
1
.
deterministic
labeling
counter
Not
defined.
map
of
flattened
nodes
A
map
containing
a
representation
of
all
nodes
in
the
graph
where
the
key
is
a
node
label
and
the
value
result
is
a
single
JSON
an
object
representation
that
has
no
nested
sub-objects
and
has
had
all
properties
for
the
same
node
merged
into
deterministically
represents
a
single
JSON
object
.
3.8.3
Normalization
Algorithm
The
normalization
algorithm
expands
the
JSON-LD
input
,
flattens
the
data
structure,
and
creates
an
initial
set
of
names
for
all
nodes
in
the
RDF
graph.
The
flattened
data
structure
is
then
processed
by
a
node
labeling
algorithm
in
order
to
get
a
fully
expanded
and
named
list
of
nodes
which
is
then
sorted.
The
result
is
a
deterministically
named
and
ordered
list
of
graph
nodes.
_:c14n
and
the
old
label
begins
with
_:c14n
then
return
as
the
node
has
already
been
renamed.
Generate
the
new
label
by
concatenating
the
labeling
prefix
with
the
string
value
of
the
labeling
counter
.
Increment
the
labeling
counter
.
For
the
node
state
associated
with
the
old
label
,
update
every
node
http://www.w3.org/1999/02/22-rdf-syntax-ns#first
,
let
object
representation
be
object
represented
in
_:c14n
@list
http://www.w3.org/1999/02/22-rdf-syntax-ns#rest
,
ignore
this
triple.
outgoing
direction
@id
incoming
direction
@id
outgoing
direction
predicate
http://www.w3.org/1999/02/22-rdf-syntax-ns#type
:
1
@type
1
.
Create
@type
,
replace
that
value
with
a
new
outgoing
direction
@type
When
normalizing
xsd:double
values,
implementers
must
ensure
that
the
normalized
value
is
a
string.
In
order
to
generate
the
string
from
a
double
value,
output
equivalent
to
the
function
in
C
must
be
used
where
printf("%1.6e",
printf("%1.6e",
value)
"%1.6e"
"%1.6e"
is
the
string
formatter
and
value
is
the
value
to
be
converted.
To convert the a double value in JavaScript, implementers can use the following snippet of code:
// the variable 'value' below is the JavaScript native double value that is to be converted (value).toExponential(6).replace(/(e(?:\+|-))([0-9])$/, '$10$2')
When data needs 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.
Some
JSON
serializers,
such
as
PHP's
native
implementation,
backslash-escapes
the
forward
slash
character.
For
example,
the
value
http://example.com/
would
be
serialized
as
http:\/\/example.com\/
in
some
versions
of
PHP.
This
is
problematic
when
generating
a
byte
stream
for
processes
such
as
normalization.
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.
Round-tripping
data
can
be
problematic
if
we
mix
and
match
@coerce
coercion
rules
with
JSON-native
datatypes,
like
integers.
Consider
the
following
code
example:
var myObj = { "@context" : { "number" : { "@id": "http://example.com/vocab#number", "@type": "xsd:nonNegativeInteger" } }, "number" : 42 }; // Map the language-native object to JSON-LD var jsonldText = jsonld.normalize(myObj); // Convert the normalized object back to a JavaScript object var myObj2 = jsonld.parse(jsonldText);
At
this
point,
myObj2
and
myObj
will
have
different
values
for
the
"number"
"number"
value.
myObj
will
be
the
number
42,
while
myObj2
will
be
the
string
"42".
"42".
This
type
of
data
round-tripping
error
can
bite
developers.
We
are
currently
wondering
if
having
a
"coerce
validation"
"coercion
validation"
phase
in
the
parsing/normalization
phases
would
be
a
good
idea.
It
would
prevent
data
round-tripping
issues
like
the
one
mentioned
above.
A JSON-LD document may be converted to any other RDF-compatible document format using the algorithm specified in this section.
The JSON-LD Processing Model describes processing rules for extracting RDF from a JSON-LD document. Note that many uses of JSON-LD may not require generation of RDF.
The processing algorithm described in this section is 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 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
s,
for
describing
externally
named
entities,
BNodes
,
resources
for
which
an
external
name
does
not
exist,
or
is
not
known,
and
Literals,
which
describe
terminal
entities
such
as
strings,
dates
and
other
representations
having
a
lexical
representation
possibly
including
an
explicit
language
or
datatype.
An Internationalized Resource Identifier ( IRI ), as described in [ RFC3987 ], is a mechanism for representing unique identifiers on the web. In Linked Data , an IRI is commonly used for expressing a subject , a property or an object .
Data
described
with
JSON-LD
may
be
considered
to
be
the
representation
of
a
graph
made
up
of
subject
and
object
resources
resource
s
related
via
a
property
resource.
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 that the following algorithm generates:
@context
key,
process
the
local
context
as
described
in
Context
.
@literal
@value
key,
set
the
active
object
to
a
literal
value
as
follows:
@datatype
@type
key
after
performing
IRI
Expansion
on
the
specified
@datatype
@type
.
@language
key,
use
it's
value
to
set
the
language
of
the
plain
literal.
@list
key
and
the
value
is
an
array
process
the
value
as
a
list
@subject
@id
key:
@subject
@id
key,
set
the
active
object
to
newly
generated
blank
node
@type
,
set
the
active
property
to
rdf:type
.
@list
coercion,
and
the
value
is
an
array
,
process
the
value
as
a
list
as
described
in
in
List
Conversion
.
@iri
@id
coercion,
set
the
active
object
by
performing
IRI
Expansion
on
the
string.
language
key
with
a
non-
null
value,
use
it's
value
to
set
the
language
of
the
plain
literal
.
xsd:integer
or
xsd:double
,
depending
on
if
the
value
contains
a
fractional
and/or
an
exponential
component.
Generate
a
triple
using
the
active
subject
,
active
property
and
the
generated
typed
literal.
xsd:boolean
.
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 .
rdf:nil
.
rdf:first
as
the
active
property
.
rdf:nil
.
rdf:rest
and
rest
blank
node
.
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
Longley,
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,
Lindstr�m,
Markus
Lanthaler,
and
Richard
Cyganiak
for
their
input
on
the
specification.
Another
huge
thank
you
goes
out
to
Dave
Longley
who
designed
many
of
The
initial
context
is
defined
with
the
algorithms
used
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
this
specification,
including
the
normalization
algorithm
which
was
a
monumentally
difficult
design
challenge.
outer-most
level
when
processing
JSON-LD
documents.
Should we define other default prefixes?