This document is licensed under a Creative Commons Attribution 3.0 License .
Developers that embed structured data in their Web pages can choose among a number of languages such as RDFa [ RDFA-CORE ], Microformats [ MICROFORMATS ] and Microdata [ MICRODATA ]. Each of these structured data languages, while incompatible at the syntax level, can be easily mapped to RDF. JSON has proven to be a highly useful object serialization and messaging format. In an attempt to harmonize the representation of Linked Data in JSON, this specification outlines a common JSON representation format for Linked Data that can be used to represent objects specified via RDFa, Microformats and Microdata.
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.
This document is a detailed specification for a serialization of JSON for Linked data. The document is primarily intended for the following audiences:
To understand this specification you must first be familiar with JSON, which is detailed in [ RFC4627 ] and [ RDF-CONCEPTS ].
There are a number of ways that one may participate in the development of this specification:
The following section outlines the design goals and rationale behind the JSON-LD markup language.
A number of design considerations were explored during the creation of this markup language:
Establishing
a
mechanism
to
map
JSON
values
to
IRIs
will
help
in
the
mapping
of
JSON
objects
to
RDF.
This
does
not
mean
that
JSON-LD
must
be
restrictive
in
declaring
a
set
of
terms,
rather,
experimentation
and
innovation
should
be
supported
as
part
of
the
core
design
of
JSON-LD.
There
are,
however,
a
number
of
very
small
design
criterial
criteria
that
can
ensure
that
developers
will
generate
good
RDF
data
that
will
create
value
for
the
greater
semantic
web
community
and
JSON/REST-based
Web
Services
community.
We will be using the following JSON object as the example for this section:
{ "a": "Person", "name": "Manu Sporny", "homepage": "http://manu.sporny.org/" "avatar": "http://twitter.com/account/profile_image/manusporny" }
A
default
context
is
used
in
RDFa
to
allow
developers
to
use
keywords
as
aliases
for
IRIs.
So,
for
instance,
the
keyword
name
above
could
refer
to
the
IRI
http://xmlns.com/foaf/0.1/name
.
The
semantic
web,
just
like
the
document-based
web,
uses
IRIs
for
unambiguous
identification.
The
idea
is
that
these
terms
mean
something,
which
you
will
eventually
want
to
query.
The
semantic
web
specifies
this
via
Vocabulary
Documents
.
The
IRI
http://xmlns.com/foaf/0.1/
specifies
a
Vocabulary
Document,
and
name
is
a
term
in
that
vocabulary.
Paste
Join
the
two
items
together
and
you
have
an
unambiguous
identifier
for
a
vocabulary
term.
The
Compact
URI
Expression,
or
short-form,
is
foaf:name
and
the
expanded-form
is
http://xmlns.com/foaf/0.1/name
.
This
vocabulary
term
identifies
the
given
name
for
something,
for
example
-
a
person's
name.
Developers, and machines, would be able to use this IRI (plugging it directly into a web browser, for instance) to go to the term and get a definition of what the term means. Much like we can use WordNet today to see the definition of words in the English language. Machines need the same sort of dictionary of terms, and URIs provide a way to ensure that these terms are unambiguous.
Non-prefixed
terms
should
have
term
mappings
declared
in
the
default
The
context
so
provides
a
collection
of
vocabulary
terms
that
they
may
can
be
expanded
later.
used
for
a
JSON
object.
If
a
set
of
terms,
like
Person
,
name
,
and
homepage
,
are
pre-defined
defined
in
the
default
a
context,
and
that
context
is
used
to
resolve
the
names
in
JSON
objects,
machines
could
automatically
expand
the
terms
to
something
meaningful
and
unambiguous,
like
this:
{"","http://www.w3.org/1999/02/22-rdf-syntax-ns#type": "http://xmlns.com/foaf/0.1/Person", "http://xmlns.com/foaf/0.1/name": "Manu Sporny","""http://xmlns.com/foaf/0.1/homepage": "http://manu.sporny.org" "http://rdfs.org/sioc/ns#avatar": "http://twitter.com/account/profile_image/manusporny" }
Doing this would mean that JSON would start to become unambiguously machine-readable, play well with the semantic web, and basic markup wouldn't be that much more complex than basic JSON markup. A win, all around.
Developers would also benefit by allowing other vocabularies to be used automatically with their JSON API. There are over 200 Vocabulary Documents that are available for use on the Web today. Some of these vocabularies are:
A
JSON-LD
Web
Service
could
define
Since
these
as
prefix
es
vocabularies
are
very
popular,
they
are
pre-defined
in
their
something
called
the
default
context
beside
the
terms
,
which
is
a
set
of
vocabulary
prefixes
that
are
already
defined.
Using
pre-loaded
in
all
JSON-LD
processors.
The
contents
of
the
default
context
are
provided
later
in
this
feature,
document.
Using
the
default
context
allows
developers
could
also
to
express
markup
data
unambiguously,
like
this:
so:
{"","rdf:type": "foaf:Person", "foaf:name": "Manu Sporny",", "sioc:avatar": "<http://twitter.com/account/profile_image/manusporny>""foaf:homepage": "http://manu.sporny.org/", "sioc:avatar": "http://twitter.com/account/profile_image/manusporny" }
Developers
can
also
specify
their
own
Vocabulary
documents
by
modifying
the
default
context
in-line
using
the
#
@context
character,
keyword,
like
so:
{, "a": "<foaf:Person>","@context": { "myvocab": "http://example.org/myvocab#" }, "a": "foaf:Person", "foaf:name": "Manu Sporny","foaf:homepage": "<http://manu.sporny.org/>", "sioc:avatar": "<http://twitter.com/account/profile_image/manusporny>", "myvocab:credits": 500"foaf:homepage": "http://manu.sporny.org/", "sioc:avatar": "http://twitter.com/account/profile_image/manusporny", "myvocab:personality": "friendly" }
Think
of
the
The
#
@context
character
as
a
"
hash
table",
which
maps
keyword
is
used
to
change
how
the
JSON-LD
processor
evaluates
key-value
pairs.
In
this
case,
it
was
used
to
map
one
string
('myvocab')
to
another
string.
string,
which
is
interpreted
as
a
IRI.
In
the
example
above,
the
myvocab
string
is
replaced
with
"
http://example.org/myvocab#
"
when
it
is
detected
above.
detected.
In
the
example
above,
"
"
would
expand
to
"
myvocab:credits
myvocab:personality
".
http://example.org/myvocab#credits
http://example.org/myvocab#personality
This
mechanism
is
a
short-hand
for
RDF,
called
a
CURIE,
and
if
defined,
will
give
provides
developers
an
unambiguous
way
to
map
any
JSON
value
to
RDF.
JSON-LD
strives
to
ensure
that
developers
don't
have
to
change
the
JSON
that
is
going
into
and
being
returned
from
their
Web
applications.
A
JSON-LD
aware
Web
Service
may
define
a
default
known
context.
For
example,
the
following
default
context
could
apply
to
all
incoming
Web
Service
calls
previously
accepting
only
JSON
data:
{"#":"@context": {"#vocab": "http://example.org/default-vocab#", "#base": "http://example.org/baseurl/","@vocab": "http://example.org/default-vocab#", "@base": "http://example.org/baseurl/", "xsd": "http://www.w3.org/2001/XMLSchema#", "dc": "http://purl.org/dc/terms/", "foaf": "http://xmlns.com/foaf/0.1/", "sioc": "http://rdfs.org/sioc/ns#", "cc": "http://creativecommons.org/ns#", "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#", "vcard": "http://www.w3.org/2006/vcard/ns#", "cal": "http://www.w3.org/2002/12/cal/ical#", "doap": "http://usefulinc.com/ns/doap#", "Person": "http://xmlns.com/foaf/0.1/Person", "name": "http://xmlns.com/foaf/0.1/name", "homepage": "http://xmlns.com/foaf/0.1/homepage" "@coerce": { "xsd:anyURI": ["foaf:homepage", "foaf:member"], "xsd:integer": "foaf:age" } } }
The
string
is
a
special
keyword
that
states
that
any
term
that
doesn't
resolve
to
a
term
or
a
prefix
should
be
appended
to
the
#vocab
@vocab
IRI.
This
is
done
to
ensure
that
terms
can
be
transformed
to
an
IRI
at
all
times.
#vocab
@vocab
The
string
is
a
special
keyword
that
states
that
any
relative
IRI
must
be
appended
to
the
string
specified
by
#base
@base
.#base
@base
The
@coerce
keyword
is
used
to
specify
type
coersion
rules
for
the
data.
For
each
key
in
the
map,
the
key
is
the
type
to
be
coerced
to
and
the
value
is
the
vocabulary
term
to
be
coerced.
Type
coersion
for
the
key
xsd:anyURI
asserts
that
all
vocabulary
terms
listed
should
undergo
coercion
to
an
IRI,
including
@base
processing
for
relative
IRIs
and
CURIE
processing
for
compact
URI
Expressions
like
foaf:homepage
.
The JSON-LD markup examples below demonstrate how JSON-LD can be used to express semantic data marked up in other languages such as RDFa, Microformats, and Microdata. These sections are merely provided as proof that JSON-LD is very flexible in what it can express across different Linked Data approaches.
The following example describes three people with their respective names and homepages.
<div prefix="foaf: http://xmlns.com/foaf/0.1/"> <ul> <li typeof="foaf:Person"> <a rel="foaf:homepage" href="http://example.com/bob/" property="foaf:name" >Bob</a> </li> <li typeof="foaf:Person"> <a rel="foaf:homepage" href="http://example.com/eve/" property="foaf:name" >Eve</a> </li> <li typeof="foaf:Person"> <a rel="foaf:homepage" href="http://example.com/manu/" property="foaf:name" >Manu</a> </li> </ul> </div>
An example JSON-LD implementation is described below, however, there are other ways to mark-up this information such that the context is not repeated.
[ {"#": { "foaf": "http://xmlns.com/foaf/0.1/" },"@": "_:bnode1", "a": "foaf:Person","foaf:homepage": "<http://example.com/bob/>","foaf:homepage": "http://example.com/bob/", "foaf:name": "Bob" }, {"#": { "foaf": "http://xmlns.com/foaf/0.1/" },"@": "_:bnode2", "a": "foaf:Person","foaf:homepage": "<http://example.com/eve/>","foaf:homepage": "http://example.com/eve/", "foaf:name": "Eve" }, {"#": { "foaf": "http://xmlns.com/foaf/0.1/" },"@": "_:bnode3", "a": "foaf:Person","foaf:homepage": "<http://example.com/manu/>","foaf:homepage": "http://example.com/manu/", "foaf:name": "Manu" } ]
The following example uses a simple Microformats hCard example to express how the Microformat is represented in JSON-LD.
<div class="vcard"><a class="url fn" href="http://tantek.com/">Tantek Çelik</a><a class="url fn" href="http://tantek.com/">Tantek Çelik</a> </div>
The
representation
of
the
hCard
expresses
the
Microformat
terms
in
the
context
and
uses
them
directly
for
the
url
and
fn
properties.
Also
note
that
the
Microformat
to
JSON-LD
processor
has
generated
the
proper
URL
type
for
http://tantek.com
.
{"#":"@context": {"vcard": "http://microformats.org/profile/hcard#vcard" "url": "http://microformats.org/profile/hcard#url" "fn": "http://microformats.org/profile/hcard#fn""vcard": "http://microformats.org/profile/hcard#vcard", "url": "http://microformats.org/profile/hcard#url", "fn": "http://microformats.org/profile/hcard#fn", "@coerce": { "xsd:anyURI": "url" } }, "@": "_:bnode1", "a": "vcard","url": "<http://tantek.com/>", "fn": "Tantek Çelik""url": "http://tantek.com/", "fn": "Tantek Çelik" }
The Microdata example below expresses book information as a Microdata Work item.
<dl itemscope itemtype="http://purl.org/vocab/frbr/core#Work" itemid="http://purl.oreilly.com/works/45U8QJGZSQKDH8N"> <dt>Title</dt> <dd><cite itemprop="http://purl.org/dc/terms/title">Just a Geek</cite></dd> <dt>By</dt> <dd><span itemprop="http://purl.org/dc/terms/creator">Wil Wheaton</span></dd> <dt>Format</dt> <dd itemprop="http://purl.org/vocab/frbr/core#realization" itemscope itemtype="http://purl.org/vocab/frbr/core#Expression" itemid="http://purl.oreilly.com/products/9780596007683.BOOK"> <link itemprop="http://purl.org/dc/terms/type" href="http://purl.oreilly.com/product-types/BOOK"> Print </dd> <dd itemprop="http://purl.org/vocab/frbr/core#realization" itemscope itemtype="http://purl.org/vocab/frbr/core#Expression" itemid="http://purl.oreilly.com/products/9780596802189.EBOOK"> <link itemprop="http://purl.org/dc/terms/type" href="http://purl.oreilly.com/product-types/EBOOK"> Ebook </dd> </dl>
Note that the JSON-LD representation of the Microdata information stays true to the desires of the Microdata community to avoid contexts and instead refer to items by their full IRI.
[ {"@": "<http://purl.oreilly.com/works/45U8QJGZSQKDH8N>","@": "http://purl.oreilly.com/works/45U8QJGZSQKDH8N", "a": "http://purl.org/vocab/frbr/core#Work", "http://purl.org/dc/terms/title": "Just a Geek", "http://purl.org/dc/terms/creator": "Whil Wheaton", "http://purl.org/vocab/frbr/core#realization":["<http://purl.oreilly.com/products/9780596007683.BOOK>", "<http://purl.oreilly.com/products/9780596802189.EBOOK>"]["http://purl.oreilly.com/products/9780596007683.BOOK", "http://purl.oreilly.com/products/9780596802189.EBOOK"] }, {"@": "<http://purl.oreilly.com/products/9780596007683.BOOK>", "a": "<http://purl.org/vocab/frbr/core#Expression>", "http://purl.org/dc/terms/type": "<http://purl.oreilly.com/product-types/BOOK>""@": "http://purl.oreilly.com/products/9780596007683.BOOK", "a": "http://purl.org/vocab/frbr/core#Expression", "http://purl.org/dc/terms/type": "http://purl.oreilly.com/product-types/BOOK" }, {"@": "<http://purl.oreilly.com/products/9780596802189.EBOOK>","@": "http://purl.oreilly.com/products/9780596802189.EBOOK", "a": "http://purl.org/vocab/frbr/core#Expression","http://purl.org/dc/terms/type": "<http://purl.oreilly.com/product-types/EBOOK>""http://purl.org/dc/terms/type": "http://purl.oreilly.com/product-types/EBOOK" } ]
The processing algorithm described in this section is provided in order to demonstrate how one might implement a JSON-LD 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.
The Processing Algorithm is a work in progress, there are still major bugs in the algorithm and it's difficult to follow. It's provided only to very early implementers to give them an idea of how to implement a processor.
#
@context
#
@context
-
Used
to
set
the
active
context.
#base
@base
-
Used
to
set
the
base
IRI
for
all
object
IRIs
affected
by
the
active
context.
#vocab
@vocab
-
Used
to
set
the
base
IRI
for
all
property
IRIs
affected
by
the
active
context.
#types
@coerce
-
Used
to
specify
type
@literal
-
Used
to
specify
a
literal
value.
@iri
-
Used
to
specify
an
IRI
value.
@language
-
Used
to
@datatype
-
Used
to
specify
the
datatype
for
a
literal.
:
-
The
separator
for
CURIEs
when
used
in
JSON
keys
or
JSON
values.
@
-
Sets
the
active
subjects.
a
-
Used
to
set
the
rdf:type
of
the
active
subjects.
The algorithm below is designed for streaming (SAX-based) implementations. Implementers will find that non-streaming (document-based) implementations will be much easier to implement as full access to the JSON object model eliminates some of the steps that are necessary for streaming implementations. A conforming JSON-LD processor must implement a processing algorithm that results in the same default graph that the following algorithm generates:
#
@context
@coerce
key
is
found,
the
processor
merges
each
key-value
pair
in
the
local
context
's
@coerce
mapping
into
the
active
context
's
@coerce
mapping,
overwriting
any
duplicate
values
in
the
active
context
's
@coerce
mapping.
Process
each
object
in
the
list
of
unprocessed
items
,
starting
at
Step
2.2
.
@
key
is
found,
the
processor
sets
the
active
subject
to
the
value
after
Object
Processing
has
been
performed.
a
key
is
found,
set
the
active
property
to
http://www.w3.org/1999/02/22-rdf-syntax-ns#type
.
#
@context
,
@
,
or
a
is
found,
,
set
the
active
property
by
performing
Property
Processing
on
the
key.
JSON-LD is designed to ensure that most Linked Data concepts can be marked up in a way that is simple to understand and author by Web developers. In many cases, Javascript objects can become Linked Data with the simple addition of a context. Since RDF is also an important sub-community of the Linked Data movement, it is important that all RDF concepts are well-represented in this specification. This section details how each RDF concept can be expressed in JSON-LD.
Expressing
IRIs
are
fundamental
to
Linked
Data
as
that
is
how
most
subjects
and
many
objects
are
identified.
IRIs
can
be
expressed
by
wrapping
in
a
text
string
with
the
<
>
characters.
variety
of
different
ways
in
JSON-LD.
<
>
@context
@
character.
@
.
,
if
it
is
a
string.
a
.
<
>
@iri
@coerce
rules
in
xsd:anyURI
for
a
particular
vocabulary
term.
An
example
of
IRI
generation
for
a
key
outside
of
a
@context
:
{
...
"http://xmlns.com/foaf/0.1/name": "Manu Sporny",
...
}
To
further
illustrate,
In
the
following
example
omissions
of
above,
the
key
<
>
http://xmlns.com/foaf/0.1/name
characters
are
allowed:
is
interpreted
as
an
IRI,
as
opposed
to
being
interpreted
as
a
string..
CURIE expansion also occurs for keys in JSON-LD:
{ ..."@": "", // CURIE/IRI when specifying the subject can be minimized. "@": "http://manu.sporny.org/about#manu","foaf:name": "Manu Sporny", ..."a": "", // CURIE/IRI when specifying the type of an object can be minimized. "a": "foaf:Person",}
foaf:name
above
will
automatically
expand
out
to
the
IRI
http://xmlns.com/foaf/0.1/name
.
An
IRI
is
generated
when
a
value
is
associated
with
a
key
using
the
@iri
keyword:
{ ..."": "<http://manu.sporny.org>", // CURIE/IRI when specifying a property can be minimized. "foaf:homepage": "<http://manu.sporny.org>","foaf:homepage": { "@iri": "http://manu.sporny.org" } ... }
At
all
other
times,
CURIEs
and
IRIs
must
be
wrapped
with
If
type
coercion
rules
are
specified
in
the
<
>
@context
characters.
for
a
particular
vocabulary
term,
an
IRI
is
generated:
{
"@context":
{
"@coerce":
{
"xsd:anyURI": "foaf:homepage"
}
}
...
"foaf:homepage": "http://manu.sporny.org",
...
}
A
subject
is
declared
using
the
@
key.
The
subject
is
the
first
piece
of
information
needed
by
the
JSON-LD
processor
in
order
to
create
the
(subject,
predicate,
property,
object)
tuple,
also
known
as
a
triple.
{ ..."","@": "http://example.org/people#joebob", ... }
The
example
above
would
set
the
subject
to
the
IRI
http://example.org/people#joebob
.
The
type
of
a
particular
subject
can
be
specified
using
the
a
key.
Specifying
the
type
in
this
way
will
generate
a
triple
of
the
form
(subject,
type,
type-url).
{ ..."@": "<http://example.org/people#joebob>", "","@": "http://example.org/people#joebob", "a": "http://xmlns.com/foaf/0.1/Person", ... }
The example above would generate the following triple (in N-Triples notation):
<http://example.org/people#joebob> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
Regular text strings are called "plain literals" in RDF and are easily expressed using regular JSON strings.
{
...
"foaf:name": "Mark Birbeck",
...
}
JSON-LD
attempts
to
make
sure
that
it
is
easy
to
express
triples
in
other
languages
while
simultaneously
ensuring
makes
an
assumption
that
hefty
data
structures
aren't
required
to
accomplish
simple
plain
literals
with
associated
language
markup.
When
the
@
symbol
encoding
information
is
not
very
common
when
used
in
JavaScript
and
Web
Services.
Thus,
it
takes
a
literal,
the
JSON-LD
processor
tags
the
literal
text
with
the
language
tag
that
follows
the
@
symbol.
little
more
effort
to
express
plain
literals
in
a
specified
language.
{ ..."foaf:name": "","foaf:name": { "@literal": "花澄", "@language": "ja" } ... }
The
example
above
would
generate
a
plain
literal
for
??
花澄
and
associate
the
ja
language
tag
with
the
triple
that
is
generated.
Languages
must
be
expressed
in
[
BCP47
]
format.
Literals
may
also
be
typed
in
JSON-LD
by
using
in
two
ways:
^^
@coerce
The
first
example
uses
the
text
string.
@coerce
keyword
to
express
a
typed
literal:
{{ "@context": { "@coerce": { "xsd:dateTime": "dc:modified" } } ..."dc:modified": "","dc:modified": "2010-05-29T14:17:39+02:00", ... }
The second example uses the expanded form for specifying objects:
{
...
"dc:modified":
{
"@literal": "2010-05-29T14:17:39+02:00",
"@datatype": "xsd:dateTime"
}
...
}
Both
examples
above
would
generate
an
object
with
the
literal
value
of
2010-05-29T14:17:39+02:00
and
the
datatype
of
http://www.w3.org/2001/XMLSchema#dateTime
.
A JSON-LD author can express multiple triples in a compact way by using arrays. If a subject has multiple values for the same property, the author may express each property as an array.
{ ..."@": "<http://example.org/people#joebob>", "foaf:nick": ,"@": "http://example.org/people#joebob", "foaf:nick": ["joe", "bob", "jaybee"], ... }
The markup shown above would generate the following triples:
<http://example.org/people#joebob> <http://xmlns.com/foaf/0.1/nick>"stu" ."joe" . <http://example.org/people#joebob> <http://xmlns.com/foaf/0.1/nick>"groknar" ."bob" . <http://example.org/people#joebob> <http://xmlns.com/foaf/0.1/nick>"radface""jaybee" .
Multiple
typed
literals
are
may
also
be
expressed
very
much
in
using
the
same
way
as
multiple
properties:
expanded
form
for
objects:
{ ..."@": "<http://example.org/articles/8>", "dcterms:modified": ],"@": "http://example.org/articles/8", "dcterms:modified": [ { "@literal": "2010-05-29T14:17:39+02:00", "@datatype": "xsd:dateTime" }, { "@literal": "2010-05-30T09:21:28-04:00", "@datatype": "xsd:dateTime" } ] ... }
The markup shown above would generate the following triples:
<http://example.org/articles/8> <http://purl.org/dc/terms/modified> "2010-05-29T14:17:39+02:00"^^http://www.w3.org/2001/XMLSchema#dateTime . <http://example.org/articles/8> <http://purl.org/dc/terms/modified> "2010-05-30T09:21:28-04:00"^^http://www.w3.org/2001/XMLSchema#dateTime .
At
times,
it
becomes
necessary
to
be
able
to
express
information
without
being
able
to
specify
the
subject.
Typically,
this
is
where
blank
nodes
come
into
play.
In
JSON-LD,
blank
node
identifiers
are
automatically
created
if
a
subject
is
not
specified
using
the
@
key.
keyword.
However,
authors
may
name
blank
nodes
by
using
the
special
_
CURIE
prefix.
{
...
"@": "_:foo",
...
}
The
example
above
would
set
the
subject
to
_:foo
,
which
can
then
be
used
later
on
in
the
JSON-LD
markup
to
refer
back
to
the
named
blank
node.
JSON-LD has a number of features that provide functionality above and beyond the core functionality provided by RDF. The following sections outline the features that are specific to JSON-LD.
Since JSON is capable of expressing typed information such as doubles, integers, and boolean values. As demonstrated below, JSON-LD utilizes that information to create Typed Literals :
{ ... // The following two values are automatically converted to a type of xsd:double // and both values are equivalent to each other. "measure:cups": 5.3, "measure:cups": 5.3e0, // The following value is automatically converted to a type of xsd:double as well "space:astronomicUnits": 6.5e73, // The following value should never be converted to a language-native type"measure:stones": ,"measure:stones": { "@literal": "4.8", "@datatype": "xsd:decimal" }, // This value is automatically converted to having a type of xsd:integer "chem:protons": 12, // This value is automatically converted to having a type of xsd:boolean "sensor:active": true, ... }
When
dealing
with
a
number
of
modern
programming
languages,
including
JavaScript
ECMA-262,
there
is
no
distinction
between
xsd:decimal
and
xsd:double
values.
That
is,
the
number
5.3
and
the
number
5.3e0
are
treated
as
if
they
were
the
same.
When
converting
from
JSON-LD
to
a
language-native
format
and
back,
datatype
information
is
lost
in
a
number
of
these
languages.
Thus,
one
could
say
that
5.3
is
a
xsd:decimal
and
5.3e0
is
an
xsd:double
in
JSON-LD,
but
when
both
values
are
converted
to
a
language-native
format
the
datatype
difference
between
the
two
is
lost
because
the
machine-level
representation
will
almost
always
be
a
double
.
Implementers
should
be
aware
of
this
potential
round-tripping
issue
between
xsd:decimal
and
xsd:double
.
Specifically
objects
with
a
datatype
of
xsd:decimal
must
not
be
converted
to
a
language
native
type.
JSON-LD supports the coercion of types to ensure that the zero-edit goal of JSON-LD can be accomplished. Type coercion allows someone deploying JSON-LD to coerce and incoming or outgoing types to the proper RDF type based on a mapping of type IRIs to RDF types. Using type conversion, one may convert simple JSON data to properly typed RDF data.
The example below demonstrates how a JSON-LD author can coerce values to plain literals, typed literals and IRIs.
{"#":"@context": { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "xsd": "http://www.w3.org/2001/XMLSchema#", "name": "http://xmlns.com/foaf/0.1/name", "age": "http://xmlns.com/foaf/0.1/age", "homepage": "http://xmlns.com/foaf/0.1/homepage","#types":"@type": {"name": "rdf:PlainLiteral", "age": "xsd:integer", "homepage": "xsd:anyURI","xsd:integer": "age", "xsd:anyURI": "homepage", } },"name": ,"name": "John Smith", "age": "41", "homepage": "http://example.org/home/" }
The example above would generate the following triples:
_:bnode1 <http://xmlns.com/foaf/0.1/name>"<John Smith>" ."John Smith" . _:bnode1 <http://xmlns.com/foaf/0.1/age> "41"^^http://www.w3.org/2001/XMLSchema#integer . _:bnode1 <http://xmlns.com/foaf/0.1/homepage> <http://example.org/home/> .
The nature of Web programming allows one to use basic technologies, such as JSON-LD, across a variety of systems and environments. This section attempts to describe some of those environments and the way in which JSON-LD can be integrated in order to help alleviate certain development headaches.
It
is
expected
that
JSON-LD
will
be
used
quite
a
bit
in
JavaScript
environments,
however,
features
like
IRIs
requiring
angled
brackets
in
JSON-LD
means
the
expanded
form
for
object
values
mean
that
using
JSON-LD
directly
in
JavaScript
is
going
to
may
be
annoying
without
a
middleware
layer
such
as
a
simple
library
that
strips
converts
JSON-LD
markup
before
JavaScript
uses
it.
One
could
say
that
JSON-LD
is
a
good
fit
for
the
RDFa
RDF
API,
which
would
enable
enables
a
triple-store
in
the
browser,
variety
of
RDF-based
Web
Applications,
but
some
don't
want
to
require
that
level
of
functionality
just
to
use
JSON-LD.
The
group
is
still
discussing
the
best
way
to
proceed,
so
input
on
how
JSON-LD
could
more
easily
be
utilized
in
JavaScript
environments
would
be
very
much
appreciated.
Databases such as CouchDB and MongoDB allow the creation of schema-less data stores. RDF is a type of schema-less data model and thus lends itself to databases such as CouchDB and MongoDB. Both of these databases can use JSON-LD as their storage format. The group needs feedback from CouchDB and MongoDB experts regarding the usefulness of JSON-LD in those environments.
There
are
a
few
advanced
concepts
where
it
is
not
clear
whether
or
not
the
JSON-LD
specification
is
going
to
support
the
complexity
necessary
to
support
each
concept.
The
entire
section
on
Advanced
Concepts
should
be
taken
with
a
grain
of
salt;
considered
as
discussion
points;
it
is
merely
a
list
of
possibilities
where
all
of
the
benefits
and
drawbacks
have
not
been
explored.
One of the more powerful features of RDFa 1.1 Core is the ability to specify a collection of prefixes and terms that can be re-used by a processor to simplfy markup. JSON-LD provides a similar mechanism called Vocabulary Profiles, which is the inclusion of a context external to the JSON-LD document.
The
example
below
demonstrates
how
one
may
specify
an
external
Vocabulary
Profile.
Assume
the
following
profile
exists
at
this
imaginary
URL:
http://example.org/profiles/contacts
.
{"#":"@context": { "xsd": "http://www.w3.org/2001/XMLSchema#", "name": "http://xmlns.com/foaf/0.1/name", "age": "http://xmlns.com/foaf/0.1/age", "homepage": "http://xmlns.com/foaf/0.1/homepage", "#types": { "age": "xsd:integer", "homepage": "xsd:anyURI", } } }
The profile listed above can be used in the following way:
{"#": { "#profile": "http://example.org/profiles/contacts" },"@profile": "http://example.org/profiles/contacts", "name": "John Smith", "age": "41", "homepage": "http://example.org/home/" }
The example above would generate the following triples:
_:bnode1 <http://xmlns.com/foaf/0.1/name> "John Smith" . _:bnode1 <http://xmlns.com/foaf/0.1/age> "41"^^http://www.w3.org/2001/XMLSchema#integer . _:bnode1 <http://xmlns.com/foaf/0.1/homepage> <http://example.org/home/> .
When serializing an RDF graph that contains two or more sections of the graph which are entirely disjoint, one must use an array to express the graph as two graphs. This may not be acceptable to some authors, who would rather express the information as one graph. Since, by definition, disjoint graphs require there to be two top-level objects, JSON-LD utilizes a mechanism that allows disjoint graphs to be expressed using a single graph.
Assume the following RDF graph:
<http://example.org/people#john> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> . <http://example.org/people#jane> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
Since the two subjects are entirely disjoint with one another, it is impossible to express the RDF graph above using a single JSON-LD associative array.
In JSON-LD, one can use the subject to express disjoint graphs as a single graph:
{"#": { "foaf": "http://xmlns.com/foaf/0.1/" },"@": [ {"@": "<http://example.org/people#john>","@": "http://example.org/people#john", "a": "foaf:Person" }, {"@": "<http://example.org/people#jane>","@": "http://example.org/people#jane", "a": "foaf:Person" } ] }
A disjoint graph could also be expressed like so:
[ { "@": "http://example.org/people#john", "a": "foaf:Person" }, { "@": "http://example.org/people#jane", "a": "foaf:Person" } ]
This API provides a clean mechanism that enables developers to convert JSON-LD data into a format that is easier to work with in various programming languages.
] interface {[NoInterfaceObject] interface JSONLDProcessor { object toProjection (in DOMString jsonld, in object? template, in DOMString? subject, in optional JSONLDParserCallback? callback); Graph toGraph (in DOMString jsonld, in optional JSONLDParserCallback? callback); };
toObject
toGraph
null
if
there
are
any
errors,
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
jsonld |
DOMString
|
|
|
The
JSON-LD
string
to
parse
into
the
|
callback |
JSONLDParserCallback
|
|
|
A callback that is called whenever a processing error occurs on the given JSON-LD string. |
object
Graph
toRDFGraph
toProjection
null
is
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
jsonld |
DOMString
|
|
|
The
JSON-LD
string
to
parse
into
the
|
|
object
| ✔ | ✘ | The Projection template to use when building the Projection. |
subject |
|
✔ | ✘ | The subject to use when building the Projection. |
callback |
JSONLDParserCallback
|
|
|
A callback that is called whenever a processing error occurs on the given JSON-LD string. |
RDFGraph
object
The JSONLDParserCallback is called whenever a processing error occurs on input data.
] interface {[NoInterfaceObject Callback] interface JSONLDProcessorCallback { void error (in DOMString error); };
The
following
example
demonstrates
how
to
convert
JSON-LD
to
a
JSON
object
projection
that
is
directly
usable
in
a
programming
environment:
// retrieve JSON-LD from a Web Service var jsonldString = fetchPerson(); // This map, usually defined once per script, defines how to map incoming // JSON-LD to JavaScript objectsvar myMap = { "http://xmlns.com/foaf/0.1/name" : "name", "http://xmlns.com/foaf/0.1/age" : "age", "http://xmlns.com/foaf/0.1/homepage" : "homepage" };var myTemplate = { "http://xmlns.com/foaf/0.1/name" : "name", "http://xmlns.com/foaf/0.1/age" : "age", "http://xmlns.com/foaf/0.1/homepage" : "homepage" }; // Map the JSON-LD to a language-native objectvar person = jsonld.toObject(jsonldString, myMap);var person = jsonld.toProjection(jsonldString, myTemplate); // Use the language-native object alert(person.name + " is " + person.age + " years old. " + "Their homepage is: " + person.homepage);
A JSON-LD Serializer is also available to map a language-native object to JSON-LD.
[NoInterfaceObject]
interface JSONLDSerializer {
DOMString normalize (in object obj);
};
normalize
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
obj |
object
|
|
|
An associative array of key-value pairs that should be converted to a JSON-LD string. It is assumed that a map already exists for the data. |
DOMString
This algorithm is very rough, untested, and probably contains many bugs. Use at your own risk. It will change in the coming months.
The JSON-LD normalization algorithm is as follows:
#
@context
key
and
preserve
it
as
the
transformation
map
while
running
this
algorithm.
Note that normalizing named blank nodes is impossible at present since one would have to specify a blank node naming algorithm. For the time being, you cannot normalize graphs that contain named blank nodes. However, normalizing graphs that contain non-named blank nodes is supported.
var myObj = { "#" : {var myObj = { "@context" : { "xsd" : "http://www.w3.org/2001/XMLSchema#", "name" : "http://xmlns.com/foaf/0.1/name", "age" : "http://xmlns.com/foaf/0.1/age", "homepage" : "http://xmlns.com/foaf/0.1/homepage","#types": { "age" : "xsd:nonNegativeInteger", "homepage" : "xsd:anyURI""@type": { "xsd:nonNegativeInteger": "age", "xsd:anyURI": "homepage" } }, "name" : "Joe Jackson", "age" : 42, "homepage" : "http://example.org/people/joe" }; // Map the language-native object to JSON-LD var jsonldText = jsonld.normalize(myObj);
After the code in the example above has executed, the jsonldText value will be (line-breaks added for readability):
{"<http://xmlns.com/foaf/0.1/age>":"42^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger>", "<http://xmlns.com/foaf/0.1/homepage>":"<http://example.org/people/joe>", "<http://xmlns.com/foaf/0.1/name>":"Joe Jackson"}[{"http://xmlns.com/foaf/0.1/age":{"@datatype":"http://www.w3.org/2001/XMLSchema#nonNegativeInteger","@literal":"42"}, "http://xmlns.com/foaf/0.1/homepage":{"@iri":"http://example.org/people/joe"}, "http://xmlns.com/foaf/0.1/name":"Joe Jackson"}]
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
printf("%1.6e",
value)
function
in
C
must
be
used
where
"%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.
The default context is provided to ensure that there are a reasonable set of prefixes and terms available to all JSON-LD developers. Mappings specified by the default context should not be overwritten by JSON-LD authors. All JSON-LD processors must load the following context in as the intial context before processing JSON-LD text.
{ "@context": { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#", "owl": "http://www.w3.org/2002/07/owl#", "xsd": "http://www.w3.org/2001/XMLSchema#", "dcterms": "http://purl.org/dc/terms/", "foaf": "http://xmlns.com/foaf/0.1/", "cal": "http://www.w3.org/2002/12/cal/ical#", "vcard": "http://www.w3.org/2006/vcard/ns# ", "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#", "cc": "http://creativecommons.org/ns#", "sioc": "http://rdfs.org/sioc/ns#", "doap": "http://usefulinc.com/ns/doap#", "com": "http://purl.org/commerce#", "ps": "http://purl.org/payswarm#", "gr": "http://purl.org/goodrelations/v1#", "sig": "http://purl.org/signature#", "ccard": "http://purl.org/commerce/creditcard#" "@coerce": { "xsd:anyURI": ["foaf:homepage", "foaf:member"], "xsd:integer": "foaf:age" } } }
The
editor
would
like
to
thank
Mark
Birbeck,
who
provided
a
great
deal
of
the
rationale
and
reasoning
behind
the
JSON-LD
work
via
his
work
on
RDFj,
Dave
Longley
who
reviewed
and
reviewed,
provided
feedback
feedback,
and
performed
several
implementation
on
the
overall
specification
and
contexts,
specification,
and
Ian
Davis,
who
created
RDF/JSON.
Thanks
also
to
Nathan
Rixham,
Bradley
P.
Allen
and
Richard
Cyganiak
for
their
input
on
the
specification.