JSON-LD - Linked Data Expression in JSON 1.0

A Context-based JSON Serialization for Linked Linking Data

Unofficial Draft 15 June 08 August 2011

Editors:
Manu Sporny , Digital Bazaar, Inc. Bazaar
Gregg Kellogg , Kellogg Associates
Authors:
Mark Birbeck Manu Sporny , Backplane Ltd. Digital Bazaar
Gregg Kellogg , Kellogg Associates
Manu Sporny Dave Longley , Digital Bazaar, Inc. Bazaar
Mark Birbeck , Backplane Ltd.

This document is also available in this non-normative format: diff to previous version .


Abstract

Developers that embed structured data in their Web pages can choose among a number of languages such as RDFa [ RDFA-CORE ], Microformats JSON [ MICROFORMATS RFC4627 ] 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 expressing directed graphs; mixing both Linked Data that can be used to represent objects specified via RDFa, Microformats and Microdata. non-Linked Data in a single document.

Status of This Document

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.

Table of Contents

1. Introduction

JSON, as specified in [ RFC4627 ], is a simple language for representing data on the Web. Linked Data is a technique for describing content across different documents or Web sites. Web resources are described using IRI s, and typically are dereferencable entities that may be used to find more information, creating a "Web of Knowledge". JSON-LD is intended to be a simple publishing method for expressing not only Linked Data in JSON, but 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 express 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 existing code that is in use today. It is designed to be able to express key-value pairs, RDF data, RDFa [ RDFA-CORE ] data, Microformats [ MICROFORMATS ] data, and Microdata. Microdata [ MICRODATA ]. That is, it supports every major Web-based structured data model in use today. It

The syntax does not require anyone many applications to change their JSON, but 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 migration path from JSON to JSON with added semantics. Finally, the format is intended to be fast to parse, fast to generate, stream-based and document-based processing compatible, and require a very small memory footprint in order to operate.

JSON, as specified in [ RFC4627 ], is a simple language for representing objects on the web. Linked Data is a way of describing content across different documents, or web resources. Web resources are described using IRI s, and typically are dereferencable entities that may be used to find more information, creating a "web of knowledge". JSON-LD is intended to be a simple publishing method for expressing linked data in JSON.

1.1 How to Read this Document

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 the basics in this specification you must first be familiar with JSON, which is detailed in [ RFC4627 ]. 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 as described in concepts [ RDF-CONCEPTS ].

Examples may contain references to existing vocabularies and use abbreviations in CURIEs and source code. The following is a list of all vocabularies and their abbreviations, as used in this document:

1.2 Contributing

There are a number of ways that one may participate in the development of this specification:

2. Design Goals and Rationale

The following section outlines the design goals and rationale behind the JSON-LD markup language.

2.1 Goals and Rationale

A number of design considerations were explored during the creation of this markup language:

Simplicity
Developers don't need to only know RDF in order JSON and three keywords to use the basic functionality provided by in JSON-LD. No extra processors or software libraries are necessary to use JSON-LD in its most basic form. The language attempts to ensure that developers have an easy learning curve.
Compatibility
The JSON-LD markup should must be 100% compatible with JSON. This ensures that all of the standard JSON libraries work seamlessly with JSON-LD documents.
Expressiveness
All major RDF concepts The syntax must be expressible via the JSON-LD syntax. able to express directed graphs, which have been proven to be able to simply express almost every real world data model.
Terseness
The JSON-LD syntax must be very terse and human readable. readable, requiring as little as possible from the developer.
Pragmatism
Mixing the expression of pure Linked Data with data that is not linked was an approach that was driven by pragmatism. JSON-LD attempts to be more practical than theoretical in its approach to Linked Data.
Zero Edits, most of the time
JSON-LD provides a mechanism that allows developers to specify context in a way that is out-of-band. This allows organizations that have already deployed large JSON-based infrastructure to add meaning to their JSON in a way that is not disruptive to their day-to-day operations and is transparent to their current customers. At times, mapping JSON to RDF a graph representation can become difficult - in difficult. In these instances, rather than having JSON-LD support esoteric markup, we chose not to support the use case and support a simplified syntax instead. So, while we strive for Zero Edits, Edits was a goal, it was not always possible without adding great complexity to the language.
Streaming
The format supports both document-based and stream-based processing.

2.2 Map Terms Linked Data

The following definition for Linked Data is the one that will be used for this specification.

  1. Linked Data is a set of documents, each containing a representation of a linked data graph.
  2. A linked data graph is a labeled directed graph, where nodes are subject s or object s, and edges are properties.
  3. A subject is any node in a linked data graph with at least one outgoing edge.
  4. A subject should be labeled with a IRI.
  5. A property is an edge of the linked data graph .
  6. A property must be labeled with an IRI.
  7. An object is a node in a linked data graph with at least one incoming edge.
  8. An object may be labeled with an IRI.
  9. An IRI that is a label in a linked data graph should be dereferencable to IRIs a Linked Data document describing the labeled subject , object or property .
  10. A literal is an object with a label that is not an IRI

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.

2.3 Linking Data

An Internationalized Resource Identifier ( IRI ) ), as described in [ RFC3987 ], is a mechanism for representing unique identifiers on the web. In Linked Data, IRIs (or URI references) are Data , an IRI is commonly used for describing entities and properties. expressing a subject , a property or an object .

Establishing JSON-LD defines a mechanism to map JSON values to IRIs will help in the mapping of JSON objects to RDF. IRIs. This does not mean that JSON-LD must requires every key or value to be restrictive in declaring a set of terms, rather, experimentation an IRI, but rather ensures that keys and innovation should values can be supported as part of mapped to IRIs if the core design of JSON-LD. developer so desires to transform their data into Linked Data. There are, however, are a number of very small design criteria few techniques that can ensure that developers will generate good RDF data that will create value Linked Data for the greater semantic web community and JSON/REST-based Web Services community. Web. JSON-LD formalizes those techniques.

We will be using the following JSON object markup as the example for the rest of this section:

{
  "a": "Person",

  "name": "Manu Sporny",
  "homepage": "http://manu.sporny.org/"

  "homepage": "http://manu.sporny.org/",

  "avatar": "http://twitter.com/account/profile_image/manusporny"
}

2.3 2.4 The JSON-LD Context

A In JSON-LD, a context is used to allow developers to use aliases for map term s to IRI s. A term is a short word that may be expanded to an IRI . The semantic web, just like the document-based web, uses IRIs for unambiguous identification. The idea is that these terms term s mean something, which you will eventually want to query. A context allows the expression of a number something that may be of terms which map directly use to IRI s. other developers. For example, the term name may map directly to the IRI http://xmlns.com/foaf/0.1/name . This allows JSON-LD documents to be constructed using the common JSON syntax practice of using simple name/value pairs. pairs while ensuring that the data is useful outside of the database or page in which it resides.

To reduce These Linked Data term s are typically collected in a context and then used by adding a single line to the number of different JSON markup above:


{
  "@context": "http://example.org/json-ld-contexts/person",
  "name": "Manu Sporny",
  "homepage": "http://manu.sporny.org/",
  "avatar": "http://twitter.com/account/profile_image/manusporny"
}

The addition above transforms the previous JSON document into a JSON document with added semantics because the @context specifies how the name , homepage , and avatar terms that must be defined, JSON-LD also map to IRIs. Mapping those keys to IRIs gives the data global context. If two developers use the same IRI to describe a property, they are more than likely expressing the same concept. This allows terms both developers to be used re-use each others data without having to expand Compact URIs ( CURIE ). agree to how their data will inter-operate on a site-by-site basis.

The semantic web specifies this via uses a special type of document called a Web Vocabulary Documents , in which to define term s. A context is a type of Web vocabulary. Typically, these Web Vocabulary documents have prefix is es associated with a document, them and contain a suffix number of term declarations. A prefix , like a term , is used a short word that expands to create an IRI based on this a Web Vocabulary IRI. Prefix es are helpful when a developer wants to mix multiple vocabularies together in a context, but does not want to go to the trouble of defining every single term in every single vocabulary. Some Web Vocabularies may have 10-20 terms defined. If a developer wants to use 3-4 different vocabularies, the number of terms that would have to be declared in a single context would become quite large. To reduce the number of different terms that must be defined, JSON-LD also allows prefixes to be used to compact IRIs.

For example, the IRI http://xmlns.com/foaf/0.1/ specifies a Web Vocabulary Document, and which may be represented using the foaf prefix . The foaf Web Vocabulary contains a term called name . If you join the foaf prefix with the name is suffix, you can build a term in compact IRI that vocabulary. Join the two items together and you have will expand out into an unambiguous identifier absolute IRI for a the http://xmlns.com/foaf/0.1/name vocabulary term. The Compact URI Expression, That is, the compact IRI, 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 - is used to specify a person's name.

Developers, and machines, would be are 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 Developers and machines need the same sort of dictionary of terms, and URIs terms. IRIs provide a way to ensure that these terms are unambiguous.

The context provides a collection of vocabulary terms term s and prefix es that can be used for a to expand JSON object. keys and values into IRI s.

2.4 2.4.1 Unambiguous Identifiers for JSON If a set of terms, like Person , name , and homepage , are defined in Inside a context, and that context is used to resolve Context

In the names in JSON objects, machines could automatically expand previous section, the terms developer used the @context keyword to pull in an external context. That context document, if de-referenced, would look something meaningful and unambiguous, like this:

{
  "",
  "": "Manu Sporny",
  "": "http://manu.sporny.org"
  "": "http://twitter.com/account/profile_image/manusporny"

    "name": "http://xmlns.com/foaf/0.1/name",
    "homepage": "http://xmlns.com/foaf/0.1/homepage",
    "avatar": "http://xmlns.com/foaf/0.1/avatar"

}

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. 2.5 Mashing Up Vocabularies 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: RDF - for describing information about objects on the semantic web. RDFS - for expressing things like labels and comments. XSD - for specifying basic types like strings, integers, dates and times. Dublin Core - for describing creative works. FOAF - for describing social networks. Calendar - for specifying events. SIOC - for describing discussions on blogs and websites. CCrel - for describing Creative Commons and other types of licenses. GEO - for describing geographic location. VCard - for describing organizations and people. DOAP - for describing projects. Since these vocabularies are very popular, they are pre-defined in something called the default JSON-LD context , which document is a set of vocabulary prefixes that are pre-loaded in all JSON-LD processors. The contents of the default context simple mapping from term are provided later in this document. Using the default context s and prefix allows developers es to express data unambiguously, like so: { "", "": "Manu Sporny", "": "http://manu.sporny.org/", "": "http://twitter.com/account/profile_image/manusporny" } Developers can expanded values such as IRIs or keywords. Contexts may also specify their own Vocabulary documents by modifying the active context contain datatype information for certain term in-line using the @context keyword, like so: { , "a": "foaf:Person", "foaf:name": "Manu Sporny", "foaf:homepage": "http://manu.sporny.org/", "sioc:avatar": "http://twitter.com/account/profile_image/manusporny", "myvocab:personality": "friendly" } The @context 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, which is interpreted s as a IRI . In the example above, the myvocab string is replaced with " http://example.org/myvocab# " when it is detected. In well as other processing instructions for the example above, " myvocab:personality " would expand to " http://example.org/myvocab#personality ". JSON-LD processor.

Contexts may be specified in-line. This mechanism is a short-hand for RDF, called ensures that JSON-LD documents can be processed when a CURIE, and provides developers an unambiguous way to map any JSON value JSON-LD processor does not have access to RDF. the Web.

2.6 An Example of a Context

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. This means that developers can also specify a context for JSON data in an out-of-band fashion via the API. The API is described later in this document. A JSON-LD aware Web Service may also define a 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/", "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": ["rdf:type", "rdf:rest", "foaf:homepage", "foaf:member"], "xsd:integer": "foaf:age" } } } The @vocab string is a special keyword that states that any term that doesn't resolve to a term or a prefix should will be appended pre-loaded for all calls to the @vocab IRI. service. This is done to ensure that terms can be transformed to an IRI at all times. The @base string is a special keyword that states allows services that any relative IRI must be appended to the string specified by @base . The @coerce keyword is used to specify type coercion rules for the data. For each key in the map, the key is the type to be coerced to have previously been publishing and the value is the vocabulary term receiving JSON data to be coerced. Type coercion for the key xsd:anyURI asserts that all vocabulary terms listed should undergo coercion accept JSON-LD data without requiring client software to an IRI, including @base processing for relative IRIs and CURIE processing for compact URI Expressions such as foaf:homepage . change.

3. 2.5 Markup Examples The JSON-LD markup examples below demonstrate how JSON-LD can be used From JSON 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. 3.1 RDFa

The following example describes three people with their respective names If a set of terms such as, name , homepage , and homepages. <div > <ul> <li > <a >Bob</a> </li> <li > <a >Eve</a> </li> <li > <a >Manu</a> </li> </ul> </div> An example JSON-LD implementation is described below, however, there avatar , are other ways to mark-up this information such defined in a context, and that the context is not repeated. [ { "@": "_:bnode1", "a": "foaf:Person", "foaf:homepage": "http://example.com/bob/", "foaf:name": "Bob" }, { "@": "_:bnode2", "a": "foaf:Person", "foaf:homepage": "http://example.com/eve/", "foaf:name": "Eve" }, { "@": "_:bnode3", "a": "foaf:Person", "foaf:homepage": "http://example.com/manu/", "foaf:name": "Manu" } ] 3.2 Microformats The following example uses a simple Microformats hCard example used to express how resolve the Microformat is represented names in JSON-LD. <div class="vcard"> <a class="url fn" href="http://tantek.com/">Tantek Çelik</a> </div> The representation of the hCard expresses JSON objects, machines are able to automatically expand 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 . something meaningful and unambiguous, like this:

{
  "@context": 
  {
    "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"

  "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"

}
3.3 Microdata 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 Doing this allows JSON to avoid contexts and instead refer be unambiguously machine-readable without requiring developers that use JSON to items by drastically change their full IRI. workflow.

[ { "@": "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", "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", "a": "http://purl.org/vocab/frbr/core#Expression", "http://purl.org/dc/terms/type": "http://purl.oreilly.com/product-types/EBOOK" } ]

4. 3. Markup of RDF Basic Concepts

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 regular JSON markup 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 As more JSON-LD features are well-represented in this specification. This section details how each RDF concept can be expressed in JSON-LD. used, more semantics are added to the JSON markup.

4.1 3.1 IRIs

Expressing IRIs are fundamental to Linked Data as that is how most subjects subject s and many objects object are identified. named. IRIs can be expressed in a variety of different ways in JSON-LD.

  1. In general, an IRI is generated if it is term s in the key position in an associative array. array that have a mapping to an IRI or another key in the context are expanded to an IRI by JSON-LD processors. There are special rules for processing keys in @context and when dealing with keys that start with the @ @subject character.
  2. An IRI is generated for the value specified using @ @subject , if it is a string.
  3. An IRI is generated for the value specified using a @type .
  4. An IRI is generated for the value specified using the @iri keyword.
  5. An IRI is generated when there are @coerce rules in effect for xsd:anyURI for a particular vocabulary term. key named @iri .

An example of IRI generation for a IRIs can be expressed directly in the key outside of a @context : position like so:

{
...
  "http://xmlns.com/foaf/0.1/name": "Manu Sporny",
...
}

In the example above, the key http://xmlns.com/foaf/0.1/name is interpreted as an IRI, as opposed to being interpreted as a string..

Term expansion occurs for IRIs if a term is defined within the active context :

{
  "@context": {"name": "http://xmlns.com/foaf/0.1/name"},
...
  "name": "Manu Sporny",
...
}

CURIE expansion also occurs for keys Prefix es are expanded when used in JSON-LD: keys:

{
  "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},

...
  "foaf:name": "Manu Sporny",
...
}

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:

{
...
  "foaf:homepage": { "@iri": "http://manu.sporny.org" }
...
}

If type coercion rules are specified in the @context for a particular vocabulary term, an IRI is generated:

{
  "@context": 
  { 

  {
    ...

    "@coerce": 
    {
      "xsd:anyURI": "foaf:homepage"
    } 

      "@iri": "foaf:homepage"
    }

  }
...
  "foaf:homepage": "http://manu.sporny.org",

  "foaf:homepage": "http://manu.sporny.org/",

...
}

Even though the value http://manu.sporny.org/ is a string, the type coercion rules will transform the value into an IRI when processed by a JSON-LD Processor

4.2 3.2 Identifying the Subject

A subject is declared using the @ @subject key. The subject is the first piece of information needed by the JSON-LD processor in order to create the (subject, property, object) tuple, also known as a triple.

{
...
  "",

  "@subject": "http://example.org/people#joebob",

...
}

The example above would set the subject to the IRI http://example.org/people#joebob .

4.3 3.3 Specifying the Type

The type of a particular subject can be specified using the a @type key. Specifying the type in this way will generate a triple of the form (subject, type, type-url).

{
...
  "@": "http://example.org/people#joebob",
  "",

  "@subject": "http://example.org/people#joebob",
  "@type": "http://xmlns.com/foaf/0.1/Person",

...
}

The example above would generate the following triple if the JSON-LD document is mapped to RDF (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>
.

4.4 3.4 Plain Literals Strings

Regular text strings are called a strings, also refered to as plain literal in RDF and s, are easily expressed using regular JSON strings.

{
...
  "foaf:name": "Mark Birbeck",
...
}

4.5 3.5 Language Specification in Plain Literals String Internationalization

JSON-LD makes an assumption that plain literal s strings with associated language encoding information is are not very common when used in JavaScript and Web Services. Thus, it takes a little more effort to express plain literals in a specified language. strings with associated language information.

{
...
  "foaf:name": 
  {
    "@literal": "花澄",
    "@language": "ja"
  }
...
}

The example above would generate a plain literal for 花澄 and associate the ja language tag code with the triple that is generated. Languages must be expressed in [ BCP47 ] format.

4.6 3.6 Typed Literals Datatypes

A value with an associated datatype, also known as a typed literal , is indicated by attaching a IRI to the end of associating a plain literal , and this with an IRI which indicates the typed literal's datatype. Literals Typed literals may be typed expressed in JSON-LD in three ways:

  1. By utilizing the @coerce keyword.
  2. By utilizing the expanded form for specifying objects.
  3. By using a native JSON datatype.

The first example uses the @coerce keyword to express a typed literal:

{
  "@context": 
  { 

  {
    "dc":  "http://purl.org/dc/terms/",
    "xsd": "http://www.w3.org/2001/XMLSchema#"

    "@coerce": 
    {
      "xsd:dateTime": "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 .

The third example uses a built-in native JSON type, a number, to express a datatype:


{
...
  "@subject": "http://example.org/people#joebob",
  "foaf:age": 31
...
}

The example above would generate the following triple:


<http://example.org/people#joebob> 
   <http://xmlns.com/foaf/0.1/age> 
"31"^^<http://www.w3.org/2001/XMLSchema#integer>
.

4.7 3.7 Multiple Objects for a Single Property

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.

In JSON-LD, Multiple objects on a property are not ordered. This is because typically graphs are not inherently ordered data structures. To see more on creating ordered collections in JSON-LD, see Lists .

{
...
  "@": "http://example.org/people#joebob",

  "@subject": "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>
      "joe" .
<http://example.org/people#joebob> 
   <http://xmlns.com/foaf/0.1/nick>
      "bob" .
<http://example.org/people#joebob> 
   <http://xmlns.com/foaf/0.1/nick>
"jaybee"
.

4.8 3.8 Multiple Typed Literals for a Single Property

Multiple typed literal s may also be expressed using the expanded form for objects:

{
...
  "@": "http://example.org/articles/8",

  "@subject": "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
.

4.9 3.9 Blank Nodes Expansion

At times, it becomes necessary to be able to express information without being able 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 when re-mapping JSON-LD documents to specify application-specific JSON documents or as a part of the subject. Typically, this Normalization process.

For example, assume the following JSON-LD input document:


{
   "name": "Manu Sporny",
   "homepage": "http://manu.sporny.org/",
   "@context": 
   {
      "name": "http://xmlns.com/foaf/0.1/name",
      "homepage": "http://xmlns.com/foaf/0.1/homepage",
      "@coerce": 
      {
         "@iri": "homepage"
      }
   }
}

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": 
   {
      "@iri": "http://manu.sporny.org/"
   }
}

3.10 Compaction

Compaction is where blank nodes come into play. In JSON-LD, blank node identifiers 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 automatically created if rarely used as keys. At times, a subject JSON-LD document may be received that is not specified using in its most compact form. JSON-LD, via the @ keyword. However, authors may name blank nodes by using API, provides a way to compact a JSON-LD document.

For example, assume the special _ CURIE prefix. following JSON-LD input document:

{
...
  "@": "",
...

   "http://xmlns.com/foaf/0.1/name": "Manu Sporny",
   "http://xmlns.com/foaf/0.1/homepage": 
   {
      "@iri": "http://manu.sporny.org/"
   }

}

The example Additionally, assume the following developer-supplied JSON-LD context:


{
   "name": "http://xmlns.com/foaf/0.1/name",
   "homepage": "http://xmlns.com/foaf/0.1/homepage",
   "@coerce": 
   {
      "@iri": ["homepage"]
   }
}

Running the JSON-LD Compaction algorithm given the context supplied above against the JSON-LD input document provided above would set result in the subject following output:


{
   "name": "Manu Sporny",
   "homepage": "http://manu.sporny.org/",
   "@context": 
   {
      "name": "http://xmlns.com/foaf/0.1/name",
      "homepage": "http://xmlns.com/foaf/0.1/homepage",
      "@coerce": 
      {
         "@iri": "homepage"
      }
   }
}

The compaction algorithm also enables the developer to map any expanded format into an application-specific compacted format. While the context provided above mapped _:foo , which http://xmlns.com/foaf/0.1/name to name , it could have also mapped it to any arbitrary string provided by the developer.

3.11 Framing

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, also called associative arrays, when dealing with JSON. While mapping a graph to a tree can be done, the layout of the end result must be specified in advance. A Frame can then be used later 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:


{
   "@coerce": {
    "dc":  "http://purl.org/dc/terms/",
    "ex":  "http://example.org/"
   },
   "@subject": 
   [{
      "@subject": "http://example.org/library",
      "@type": "ex:Library",
      "ex:contains": "http://example.org/library/the-republic"
   }, 
   {
      "@subject": "http://example.org/library/the-republic",
      "@type": "ex:Book",
      "dc:creator": "Plato",
      "dc:title": "The Republic",
      "ex:contains": "http://example.org/library/the-republic#introduction"
   }, 
   {
      "@subject": "http://example.org/library/the-republic#introduction",
      "@type": "ex:Chapter",
      "dc:description": "An introductory chapter on The Republic.",
      "dc:title": "The Introduction"
   }],
   "@context": 
   {
      "@coerce": 
      {
         "@iri": "ex:contains"
      },
      "dc": "http://purl.org/dc/elements/1.1/",
      "ex": "http://example.org/vocab#"
   }
}

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": {
      "dc": "http://purl.org/dc/elements/1.1/",
      "ex": "http://example.org/vocab#"
   },
   "@type": "ex:Library",
   "ex:contains": {
      "@type": "ex:Book",
      "ex:contains": {
         "@type": "ex:Chapter"
      }
   }
}

When the framing algorithm is run against the previously defined JSON-LD markup document, paired with the frame above, the following JSON-LD document is the end result:


{
   "@context": 
   {
      "ex": "http://example.org/vocab#",
      "dc":  "http://purl.org/dc/terms/",
   }
   "@subject": "http://example.org/library",
   "@type": "ex:Library",
   "ex:contains": 
   {
      "@subject": "http://example.org/library/the-republic",
      "@type": "ex:Book",
      "dc:creator": "Plato",
      "dc:title": "The Republic",
      "ex:contains": 
      {
         "@subject": "http://example.org/library/the-republic#introduction",
         "@type": "ex:Chapter",
         "dc:description": "An introductory chapter on The Republic.",
         "dc:title": "The Introduction"
      },
   },
}

The JSON-LD framing algorithm allows developers to refer back query by example and force a specific tree layout to the named blank node. a JSON-LD document.

5. 4. Advanced Features Concepts

JSON-LD has a number of features that provide functionality above and beyond the core functionality provided by RDF. described above. The following sections outline the features that are specific to JSON-LD.

5.1 4.1 Automatic Typing

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 literal s:

{
...
  // 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": { "@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.

5.2 4.2 Type Coercion

JSON-LD supports the coercion of types values to ensure that the zero-edit goal of JSON-LD can be accomplished. particular data types. Type coercion allows someone deploying JSON-LD to coerce and the incoming or outgoing types to the proper RDF data type based on a mapping of data type IRIs to RDF property types. Using type conversion, coercion, 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 literal s, typed literal s 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",
     "@coerce":
     {
        "xsd:integer": "age",
        "xsd:anyURI": "homepage",

        "@iri": "homepage"

     }
  },
  "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/>
.

6. 4.3 The JSON-LD Processing Algorithm Chaining

The JSON-LD Processing Model describes processing rules for extracting RDF from Object chaining is a JSON-LD document. Note feature that many uses allows an author to use the definition of JSON-LD may not require generation of RDF. objects as property values. This is a commonly used mechanism for creating a parent-child relationship between two subject s.

The processing algorithm described in this section is provided in order to demonstrate how one might implement example shows an two subjects related by a JSON-LD processor. Conformant implementations are only required to produce the same type and number of triples during property from the output process and are not required to implement first subject:


{
...
  "foaf:name": "Manu Sporny",
  "foaf:knows": {
    "@type": "foaf:Person",
    "foaf:name": "Gregg Kellogg",
  }
...
}

An object definition, like the algorithm exactly one used above, may be used as described. The Processing Algorithm is a work JSON value at any point in progress. JSON-LD.

6.1 4.4 Overview Identifying Unlabeled Nodes

This section is non-normative. JSON-LD is intended At times, it becomes necessary to have an easy be able to parse grammar that closely models existing practice in using JSON for describing object representations. This allows express information without being able to specify the use subject. Typically, this type of existing libraries for parsing JSON in a document-oriented fashion, node is called an unlabeled node or can allow for stream-based parsing similar to SAX. As with other grammars used for describing linked data, a key concept is that of blank node. In JSON-LD, unlabeled node identifiers are automatically created if a resource . Resources subject is not specified using the @subject keyword. However, authors may be of three basic types: IRI s, for describing externally named entities, BNodes , resources provide identifiers for unlabeled nodes by using the special _ (underscore) CURIE prefix.


{
...
  "@subject": "_:foo",
...
}

The example above would set the subject to _:foo , which an external name does not exist, or can then be used later on in the JSON-LD markup to refer back to the unlabeled node. This practice, however, is not known, and Literals, which describe terminal entities such as strings, dates and other representations having usually frowned upon when generating Linked Data. If a lexical representation possibly including an explicit language or datatype. developer finds that they refer to the unlabeled node more than once, they should consider naming the node using a resolve-able IRI.

4.5 Overriding Keywords

Data described with JSON-LD may allows all of the syntax keywords, except for @context , to be considered overridden. This feature allows more legacy JSON content to be the representation of a graph made up of subject and object resources related via a predicate resource. However, specific implementations may choose supported by JSON-LD. It also allows developers to operate on design domain-specific implementations using only the document as JSON-LD context.


{
  "@context": 
  {  
     "url": "@subject",     "a": "@type",
     "name": "http://schema.org/name"
  },
  "url": "http://example.com/about#gregg",
  "a": "http://schema.org/Person",
  "name": "Gregg Kellogg"
}

In the example above, the @subject and @type keywords have been overridden by url and a normal JSON description of objects having attributes. , respectively.

6.2 4.6 Processing Algorithm Terms Normalization

default context a context that

Normalization is specified to the process of taking JSON-LD processing algorithm before processing begins. default graph input and performing a deterministic transformation on that input that results in a JSON-LD output that any conforming JSON-LD processor would have generated given the destination same input. The problem is a fairly difficult technical problem to solve because it requires a directed graph for to be ordered into a set of nodes and edges in a deterministic way. This is easy to do when all triples generated by JSON-LD markup. active subject of the currently active subject that nodes have unique names, but very difficult to do when some of the processor should use nodes are not labeled.

Normalization is useful when comparing two graphs against one another, when generating triples. active property the currently active property that the processor should use a detailed list of differences between two graphs, and when generating triples. active object the currently active object that the processor should use a cryptographic digital signature for information contained in a graph or when generating triples. active context a context that is used to resolve CURIEs while hash of the processing algorithm information contained in a graph.

The example below is running. an un-normalized JSON-LD document:


{
   "name": "Manu Sporny",
   "homepage": "http://manu.sporny.org/",
   "@context": 
   {
      "name": "http://xmlns.com/foaf/0.1/name",
      "homepage": "http://xmlns.com/foaf/0.1/homepage",
      "xsd": "http://www.w3.org/2001/XMLSchema#",
      "@coerce": 
      {
         "@iri": ["homepage"]
      }
   }
}

The active context example below is the context contained within normalized form of the processor state . local context a context that JSON-LD document above:

Whitespace is specified at the JSON associative-array level, specified via used below to aid readability. The normalization algorithm for JSON-LD remove all unnecessary whitespace in the @context keyword. processor state fully normalized form.


[{
    "@subject": 
    {
        "@iri": "_:c14n0"
    },
    "http://xmlns.com/foaf/0.1/homepage": 
    {
        "@iri": "http://manu.sporny.org/"
    },
    "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
}]

Notice how all of the processor state , which includes term s have been expanded and sorted in alphabetical order. Also, notice how the active context , current subject , and current property . The processor state is managed as a stack has been labeled with elements from the previous processor state copied into a new processor state when entering a new associative array. blank node identifier . Normalization ensures that any arbitrary graph containing exactly the same information would be normalized to exactly the same form shown above.

5. Algorithms

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.

6.3 5.1 Processing Syntax Tokens and Keywords

JSON-LD specifies a number of syntax tokens and keywords that are using in all algorithms described in this section:

@context
Used to set the local context .
@base
Used to set the base IRI for all object IRIs affected by the active context .
@profile A reference to a remote context description used to set the local context . @vocab
Used to set the base IRI for all property IRIs affected by the active context .
@coerce
Used to specify type coercion rules.
@literal
Used to specify a literal value.
@iri
Used to specify an IRI value.
@language
Used to specify the language for a literal.
@datatype
Used to specify the datatype for a literal.
:
The separator for CURIEs when used in JSON keys or JSON values.
@ @subject
Sets the active subjects.
a @type
Used to set the rdf:type type of the active subjects. This token may be conferred as syntactic sugar for rdf:type.
Use @source instead of @ ? Use

5.2 Algorithm Terms

initial context
a context that is specified to the algorithm before processing begins.
active subject
the currently active subject that the processor should use when processing.
active property
the currently active property that the processor should use when processing.
active object
the currently active object that the processor should use when processing.
active context
a context that is used to resolve CURIEs while the processing algorithm is running. The active context is the context contained within the processor state .
local context
a context that is specified at the JSON associative-array level, specified via the @type @context instead of keyword.
processor state
the processor state , which includes the active context , current subject , and current property . The processor state is managed as a ? Note stack with elements from the previous processor state copied into a new processor state when entering a new associative array.
JSON-LD input
The JSON-LD data structure that both are just semantic sugar for rdf:type . is provided as input to the algorithm.
JSON-LD output
The JSON-LD data structure that is produced as output by the algorithm.

6.4 5.3 Context

Processing of JSON-LD data structure is managed recursively using a process described in Sequence . 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 default initial context . If a local context is encountered, information from the local context is merged into the active context .

Should the document URL be used as the default for @base in the default context ?

The active context is used for expanding keys and values of an associative array (or elements of a list (see List Processing )).

A local context is identified within an associative array having a key of @context with string or an associative array value. When processing a local context , special processing rules apply:

  1. The key Create a new, empty local context .
  2. If the value is a simple string, it must have a lexical form of IRI and used to initialize a new JSON document which replaces the value for subsequent processing.
  3. If the value is an associative array, perform the following steps:
    1. If the associative array has a @base key, it must have a value of a simple string with the lexical form of IRI and is saved in an absolute IRI. Add the active base mapping to the local context .

      Turtle allows @base to perform term mapping as described in be relative. If we did this, we would have to add IRI Processing Expansion .

    2. The key If the associative array has a @vocab key, it must have a value of a simple string with the lexical form of IRI and is saved in an absolute IRI. Add the active vocabulary mapping to the local context to perform term mapping as described in after performing IRI Processing . Expansion on the associated value.
    3. The key If the associative array has a @coerce key, it must have a value of an associative array. Processing of Add the associative array is described below @coerce mapping to the local context performing IRI Expansion on the associated value(s).
    4. Otherwise, the key must have the lexical form of NCName and must have the value of a simple string with the lexical form of IRI. Merge each the key-value pair into the active local context , overwriting any duplicate values. .
    5. A
  4. Merge the of local context may also be loaded from an external document using 's @coerce mapping into the active context 's @profile @coerce key mapping as described in Vocabulary Profiles below .
  5. Merge all entries other than the @coerce mapping from the local context to the active context overwriting any duplicate values.

6.4.1 5.3.1 Coerce

Map 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. The @coerce mapping has a either of a single CURIE or of an array of CURIEs. When merging with an existing mapping in the active context , map all CURIE 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 CURIE, the processor may represent this as a string value.

6.5 5.3.2 Chaining Initial Context

Object chaining The initial context is a JSON-LD feature that allows an author to use the definition of JSON-LD objects initialized as property values. This follows:

  • @base is set using section 5.1 Establishing a commonly used mechanism for creating Base URI of [ RFC3986 ]. Processors may provide a parent-child relationship between objects. The example shows an two objects related by means of setting the base IRI programatically.
  • @coerce is set with a property single mapping from the first object: @iri to @type .
{
...
  "foaf:name": "Manu Sporny",
  "": {
    "",
    "",
  }
...

    "@base": document-location,
    "@context": {
      "@iri": "@type"
    }

}
An object definition may be used anyplace a value is legal in JSON-LD.

6.6 5.4 IRI Processing Expansion

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 may be represented as an explicit string, or as a CURIE, as a value relative to @base or @vocab .

CURIEs are defined more formally in [ RDFA-CORE ] section 6 "CURIE Syntax Definition" . Generally, a CURIE is composed of a prefix and a suffix separated by a ':'. In JSON-LD, either the prefix may be the empty string, denoting the default prefix .

The procedure algorithm for generating an IRI is:

  1. Split the value into a prefix and suffix from the first occurrence of ':'.
  2. If the prefix is a '_', generate a named BNode using the suffix as '_' (underscore), the name. IRI is unchanged.
  3. If the active context contains a mapping for prefix , generate an IRI by prepending the mapped prefix to the (possibly empty) suffix. suffix using textual concatenation. Note that an empty suffix and no suffix (meaning the value contains no ':' string at all) are treated equivalently.
  4. If the IRI being processed is for a property (i.e., a key value in an associative array, or a value in a @coerce mapping) and the active context has a @vocab mapping, join the mapped value to the suffix using the method described in [ RFC3987 ]. textual concatenation.
  5. If the 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 to the suffix using the method described in [ RFC3987 RFC3986 ].
  6. Otherwise, use the value directly as an IRI.

5.5 IRI Compaction

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 and prefix es specified in the local context .

The algorithm for generating a compacted IRI is:

  1. Search every key-value pair in the active context for a term that is a complete match against the IRI. If a complete match is found, the resulting compacted IRI is the term associated with the IRI in the active context .
  2. If a complete match is not found, search for a partial match from the beginning of the IRI. For all matches that are found, the resulting compacted IRI is the prefix associated with the partially matched IRI in the active context concatenated with a colon (:) character and the unmatched part of the string. If there is more than one compacted IRI produced, the final value is the lexicographically least value of the entire set of compacted IRIs.

7. 5.6 Sequence Value Expansion

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:

  1. If the key that is associated with the value has an associated coercion entry in the local context , the resulting expansion is an object populated according to the following steps:
    1. If the coercion target is @iri , expand the value by adding a new key-value pair where the key is @iri and the value is the expanded IRI according to the IRI Expansion rules.
    2. If the coercion target is a typed literal, expand the value by adding two new key-value pairs. The first key-value pair will be @literal and the unexpanded value. The second key-value pair will be @datatype and the associated coercion datatype expanded according to the IRI Expansion rules.

5.7 Value Compaction

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 value is:

  1. If the local context contains a coercion target for the key that is associated with the value, compact the value using the following steps:
    1. If the coercion target is an @iri , the compacted value is the value associated with the @iri key, processed according to the IRI Compaction steps.
    2. If the coercion target is a typed literal, the compacted value is the value associated with the @literal key.
    3. Otherwise, the value is not modified.

5.8 Expansion

This algorithm is a work in progress, do not implement it.

As stated previously, expansion is the process of taking a JSON-LD input and expanding all IRIs and typed literals to their fully-expanded form. The output will not contain a single context declaration and will have all IRIs and typed literals fully expanded.

5.8.1 Expansion Algorithm

  1. If the top-level item in the JSON-LD input is an array, process each item in the array recursively using this algorithm.
  2. If the top-level item in the JSON-LD input is an object, update the local context according to the steps outlined in the context section. Process each key, expanding the key according to the IRI Expansion rules.
    1. Process each value associated with each key
      1. If the value is an array, process each item in the array recursively using this algorithm.
      2. If the value is an object, process the object recursively using this algorithm.
      3. Otherwise, check to see the associated key has an associated coercion rule. If the value should be coerced, expand the value according to the Value Expansion rules. If the value does not need to be coerced, leave the value as-is.
    2. Remove the context from the object

5.9 Compaction

This algorithm is a work in progress, do not implement it.

As stated previously, compaction is the process of taking a JSON-LD input and compacting all IRIs using a given context. The output will contain a single top-level context declaration and will only use term s and prefix es and will ensure that all typed literals are fully compacted.

5.9.1 Compaction Algorithm

  1. Perform the Expansion Algorithm on the JSON-LD input .
  2. If the top-level item is an array, process each item in the array recursively, starting at this step.
  3. If the top-level item is an object, compress each key using the steps defined in IRI Compaction and compress each value using the steps defined in Value Compaction

5.10 Framing

This algorithm is a work in progress, do not implement it.

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 don't work directly with graphs, but rather, prefer trees when dealing with JSON. While mapping a graph to a tree can be done, the layout of the end result must be specified in advance. This section defines an algorithm for mapping a graph to a tree given a frame .

5.10.1 Framing Algorithm Terms

input frame
the initial frame provided to the framing algorithm.
framing context
a context containing the object embed flag , the explicit inclusion flag and the omit default flag .
object embed flag
a flag specifying that objects should be directly embedded in the output, instead of being referred to by their IRI.
explicit inclusion flag
a flag specifying that for properties to be included in the output, they must be explicitly declared in the framing context .
omit missing properties flag
a flag specifying that properties that are missing from the JSON-LD input should be omitted from the output.
match limit
A value specifying the maximum number of matches to accept when building arrays of values during the framing algorithm. A value of -1 specifies that there is no match limit.
map of embedded subjects
A map that tracks if a subject has been embedded in the output of the Framing Algorithm .

5.10.2 Framing Algorithm

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:

  1. Initialize the framing context by setting the object embed flag , clearing the explicit inclusion flag , and clearing the omit missing properties flag . Override these values based on input options provided to the algorithm by the application.
  2. Generate a list of frames by processing the expanded frame :
    1. If the expanded frame is not an array, set match limit to 1, place the expanded frame into the list of frames , and set the JSON-LD output to null .
    2. If the expanded frame is an empty array, place an empty object into the list of frames , set the JSON-LD output to an array, and set match limit to -1.
    3. If the expanded frame is a non-empty array, add each item in the expanded frame into the list of frames , set the JSON-LD output to an array, and set match limit to -1.
  3. Create a match array for each expanded frame in the list of frames halting when either the match limit is zero or the end of the list of frames is reached. If an expanded frame is not an object, the processor must throw a Invalid Frame Format exception. Add each matching item from the normalized input to the matches array and decrement the match limit by 1 if:
    1. The expanded frame has an 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.
    2. The expanded frame does not have an rdf:type property, but every property in the expanded frame exists in the item.
  4. Process each item in the match array with its associated match frame :
    1. If the match frame contains an @embed keyword, set the object embed flag to its value. If the match frame contains an @explicit keyword, set the explicit inclusion flag to its value. Note: if the keyword exists, but the value is neither true or false , set the associated flag to true .
    2. If the object embed flag is cleared and the item has the @subject property, replace the item with the value of the @subject property.
    3. If the object embed flag is set and the item has the @subject property, and its IRI is in the map of embedded subjects , throw a Duplicate Embed exception.
    4. If the object embed flag is set and the item has the @subject property and its IRI is not in the map of embedded subjects :
      1. If the explicit inclusion flag is set, then delete any key from the item that does not exist in the match frame , except @subject .
      2. For each key in the match frame , except for keywords and rdf:type :
        1. If the key is in the item, then build a new recursion input list using the object or objects associated with the key. If any object contains an @iri value that exists in the normalized input , replace the object in the recusion input list with a new object containing the @subject key where the value is the value of the @iri , 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.
        2. If the key is not in the item, add the key to the item and set the associated value to an empty array if the match frame key's value is an array or null otherwise.
        3. If value associated with the item's key is null , process the omit missing properties flag :
          1. If the value associated with the key in the match frame is an array, use the first frame from the array as the property frame , otherwise set the property frame to an empty object.
          2. If the property frame contains an @omitDefault keyword, set the omit missing properties flag to its value. Note: if the keyword exists, but the value is neither true or false , set the associated flag to true .
          3. If the omit missing properties flag is set, delete the key in the item. Otherwise, if the @default keyword is set in the property frame set the item's value to the value of @default .
    5. If the JSON-LD output is null set it to the item, otherwise, append the item to the JSON-LD output .
  5. Return 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.

5.11 Normalization

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 and named in the JSON-LD output . The normalized output is generated in such a way that any conforming JSON-LD processor will generate identical output given the same input. The problem is a fairly difficult technical problem to solve because it requires a directed graph to be ordered into a set of nodes and edges in a deterministic way. This is easy to do when all of the nodes have unique names, but very difficult to do when some of the nodes are not labeled.

In time, there may be more than one normalization algorithm that will need to be identified. For identification purposes, this algorithm is named UGNA2011 .

5.11.1 Normalization Algorithm Terms

list of expanded nodes
A list of all nodes in the JSON-LD input graph containing no embedded objects and having all keys and values expanded according to the steps in the Expansion Algorithm .
naming base string
An unlabeled node naming prefix that is not used by any other node in the JSON-LD input and does not start with the characters c14n . The prefix 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.
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.
naming base string
An unlabeled node naming prefix that is not used by any other node in the JSON-LD input and does not start with the characters c14n . The prefix 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.

5.11.2 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 graph. The flattened data structure is then processed by the node labeling algorithm in order to get a fully expanded and named list of nodes.

  1. Expand the JSON-LD input according to the steps in the Expansion Algorithm and store the result as the expanded input .
  2. Process every object in the expanded input searching for @subject values that start with the text string _:c14n . If a match is found, rename the subject and all references to the subject by concatenating _: with the naming base string and a unique identifier, such as an incremented counter value.
  3. Create an empty list of expanded nodes and recursively process every object in the expanded input that is not an expanded IRI, typed literal or language literal, in depth-first order:
    1. If an object does not contain a @subject , name it by concatenating _: with the naming base string and a unique identifier, such as an incremented counter value.
    2. Add the object to the list of expanded nodes .
    3. Replace the reference to the object with the value of the @subject in the object.
    4. ???duplicate objects for predicates???
  4. Label all of the nodes that contain a @subject key associated with a value starting with _: according to the steps in the Node Labeling Algorithm .

5.11.3 Node Labeling Algorithm

The node labeling algorithm takes the list of expanded nodes and sorts the list, deterministically naming all of the unlabeled nodes in the graph.

  1. Create a forward mapping that relates graph nodes to the IRIs of the targets nodes that they reference. For example, if a node alpha refers to a node beta via a property, the key in the forward mapping is the subject IRI of alpha and the value is an array containing at least the subject IRI of beta .
    1. Add all forward mappings for every node in the graph.
  2. Create a reverse mapping that relates graph nodes to every other node that refers to them in the graph. For example, if a node alpha refers to a node beta via a property, the key in the reverse mapping is the subject IRI for beta and the value is an array containing at least the IRI for alpha .
    1. Add all reverse mappings for every node in the graph.
  3. Label every unlabeled node according to the Label Generation Algorithm in descending order using the Deep Comparison Algorithm to determine the sort order.

5.11.4 Shallow Comparison Algorithm

The shallow comparison algorithm takes two unlabeled nodes, alpha and beta , as input and determines which one should come first in a sorted list. The following algorithm determines the steps that are executed in order to determine the node that should come first in a list:

  1. Compare the total number of node properties. The node with fewer properties is first.
  2. Lexicographically sort the property IRIs for each node and compare the sorted lists. If an IRI is found to be lexicographically smaller, the node containing that IRI is first.
  3. Compare the property values against one another:
    1. Create an alpha list by adding all values associated with the alpha property that is not an unlabeled node. Track the number of unlabeled nodes not added to the list using an alpha unlabeled counter .
    2. Create a beta list by adding all values associated with the beta property that is not an unlabeled node. Track the number of unlabeled nodes not added to the list using an beta unlabeled counter .
    3. Compare the length of alpha list and beta list . The node associated with the list containing the lesser number of items is first.
    4. Compare the alpha unlabeled counter to the beta unlabeled counter , the node associated with the lesser value is first.
    5. Sort alpha list and beta list using the Object Comparison Algorithm as the sorting comparator. For each offset into the alpha list , compare the item at the offset against the item at the same offset in the beta list using the Object Comparison Algorithm . The node associated with the lesser item is first.
  4. Process the reverse mapping to determine order:
    1. The node with fewer entries in the reverse mapping is first.
    2. Sort the reverse mapping entry for alpha into a list of sorted alpha mappings . Sort the reverse mapping entry for beta into a list of sorted beta mappings .
    3. The node associated with the list of sorted mappings with the least number of unlabeled nodes is first.
    4. For each offset into the list of sorted alpha mappings , compare the IRI at the offset against the IRI at the same offset in the list of sorted beta mappings . The node associated with the lexicographically lesser IRI is first.
  5. Otherwise, the nodes are equal.

5.11.5 Object Comparison Algorithm

The object comparison algorithm is designed to compare two graph node property values, alpha and beta , against the other. The algorithm is useful when sorting two lists of graph node properties.

  1. If one of the values is a string and the other is not, the value that is a string is first.
  2. If both values are strings, the lexicographically lesser string is first.
  3. If one of the values is a literal and the other is not, the value that is a literal is first.
  4. If both values are literals
    1. The lexicographically lesser string associated with @literal is first.
    2. The lexicographically lesser string associated with @datatype is first.
    3. The lexicographically lesser string associated with @language is first.
  5. If both values are expanded IRIs, the lexicographically lesser string associated with @iri is first.
  6. Otherwise, the two values are equivalent.

5.11.6 Deep Comparison Algorithm

DeepCompare(bnodeA, bnodeB):

  1. Return the value of ShallowCompare if it is non-zero.
  2. Compare property serializations and then reference serializations, recycling the mapping from property serializations for reference serializations.
    1. If the serialization for bnodeA is null, do SerializeNode(bnodeA, new Mapping).
    2. If the serialization for bnodeB is null, do SerializeNode(bnodeA, new Mapping).
    3. Return the result of a lexicographical comparison of the two serializations.

5.11.7 Node Serialization Algorithm

SerializeNode(bnode, mapping, dir):

  1. If the bnode's label is already marked as mapped, return.
  2. Mark the bnode's label as mapped.
  3. Assign the next serialization name to the bnode's label and store it in "top".
  4. Split the bnode's adjacent bnodes into a map and a list. The map contains a reverse mapping of serialization names to bnode labels for all labels in the mapping, the list (notMapped) contains all labels not in the mapping yet.
  5. Save a copy of the mapping.
  6. Do SerializeCombos for max(1, notMapped.length) using the original mapping for the first call and a copy of the mapping for each subsequent call.

5.11.8 Combinatorial Serialization Algorithm

SerializeCombos(top, mapping, mapped, notMapped, dir):

  1. If notMapped is non-empty, copy mapped and assign the next serialization name to its first bnode, remove it from the list, and update mapped.
    1. For max(1, notMapped.length) recurse into SerializeCombos with the original mapping for the first call and a copy of the mapping for each subsequent call. Rotate notMapped on each iteration.
  2. If notMapped is empty, save an entry mapping from the bnode's serialization name to the reverse mapping (mapped) and its sorted keys then do SerializeMapping.
    1. If the serialization is lexicographically less than the current serialization or the current serialization is null, then iterate over the sorted keys, get the reverse-mapped adjacent bnode and recursively call SerializeNode on each iteration.
    2. Do SerializeMapping then if the serialization is lexicographically less than the current serialization or the current serialization is null, then set it as the least serialization for the bnode in the given edge direction ('property' or 'reference').

5.11.9 Mapping Serialization Algorithm

SerializeMapping(mapping): (This function incrementally updates the relation serialization for a mapping)

  1. If there is an entry on the mapping's key stack, pop it and iterate over every key.
  2. For each key, if an entry for the key hasn't been added to the mapping yet, break out of the loop.
  3. Update the key stack entry's index.
  4. If the key has already been serialized, output "'_' + key" and continue.
  5. For each key, serialize the key then its associated bnode properties, then its bnode references. The entire property list is surrounded by '[' and ']' and so is the reference list. Individual properties/references are seperated by '|'. If a property is an array, all of the serializations are concatenated together with no joining delimiter. The '@subject' property is skipped. The property IRI is turtle-serialized. If a property or reference object is a bnode, it is serialized to '_:', otherwise the turtle serialization is used.
  6. Join all of the adjacent keys and add them to the serialization.
  7. Push the adjacent keys onto the key stack.
  8. Do SerializeMapping.

5.11.10 Label Generation Algorithm

NameNode(bnode):

  1. Remove the first blank node from the list of sorted blank nodes.
  2. Give it the next canonical name.
  3. Give canonical names to each blank node key in its property serialization mapping in lexicographical order.
  4. Give canonical names to each blank node key in its reference serialization mapping in lexicographical order.
  5. Set all serializations containing newly-named blank nodes to null.

5.12 Data Round Tripping

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.

Round-tripping data can be problematic if we mix and match @coerce rules with JSON-native datatypes, like integers. Consider the following code example:


var myObj = { "@context" : { 
                "number" : "http://example.com/vocab#number",
                "@coerce": {
                   "xsd:nonNegativeInteger": "number"
                }
              },
              "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" value. myObj will be the number 42, while myObj2 will be the string "42". This type of data round-tripping error can bite developers. We are currently wondering if having a "coerce validation" phase in the parsing/normalization phases would be a good idea. It would prevent data round-tripping issues like the one mentioned above.

5.13 RDF Conversion

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.

The RDF Conversion Algorithm is a work in progress.

5.13.1 Overview

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 in a document-oriented fashion, or can allow for stream-based parsing similar to SAX.

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.

Data described with JSON-LD may be considered to be the representation of a graph made up of subject and object resources related via a property resource. However, specific implementations may choose to operate on the document as a normal JSON description of objects having attributes.

5.13.2 RDF Conversion Algorithm Terms

default graph
the destination graph for all triples generated by JSON-LD markup.

5.13.3 RDF Conversion Algorithm

The algorithm below is designed for in-memory implementations with random access to associative array elements. For a description of a streaming implementation, see Appendix B .

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:

  1. Create a new processor state with with the active context set to the default initial context and active subject and active property initialized to NULL.
  2. If an associative array is detected, perform the following steps:
    1. If the associative array has a @context key, process the local context as described in Context .
    2. Create a new associative array by mapping the keys from the current associative array using the active context to new keys using the associated value from the current associative array. Repeat the mapping until no entry is found within the active context for the key. Use the new associative array in subsequent steps.
    3. If the associative array has an @iri key, set the active object by performing IRI Processing Expansion on the associated value. Generate a triple representing the active subject , the active property and the active object . Return the active object to the calling location.

      @iri really just behaves the same as @subject , consider consolidating them.

    4. If the associative array has a @literal key, set the active object to a literal value as follows:
      1. as a typed literal if the associative array contains a @datatype key after performing IRI Processing Expansion on the specified @datatype .
      2. otherwise, as a plain literal . If the associative array contains a @language key, use it's value to set the language of the plain literal.
      3. Generate a triple representing the active subject , the active property and the active object . Return the active object to the calling location.
    5. If the associative array has a @ @subject key:
      1. If the value is a string, set the active object to the result of performing IRI Processing Expansion . Generate a triple representing the active subject , the active property and the active object . Set the active subject to the active object .
      2. Create a new processor state using copies of the active context , active subject and active property and process the value starting at Step 2 , set the active subject to the result and proceed using the previous processor state .
    6. If the associative array does not have a @ @subject key, set the active object to newly generated blank node identifier . . Generate a triple representing the active subject , the active property and the active object . Set the active subject to the active object .
    7. For each key in the associative array that has not already been processed, perform the following steps:
      1. If the key is a @type , set the active property to rdf:type .
      2. Otherwise, set the active property to the result of performing IRI Processing Expansion on the key.
      3. Create a new processor state copies of the active context , active subject and active property and process the value starting at Step 2 and proceed using the previous processor state .
    8. Return the active object to the calling location.
  3. If a regular array is detected, process each value in the array by doing the following returning the result of processing the last value in the array:
    1. If the value is a regular array, generate an RDF List by linking each element of the list using rdf:first and rdf:next , terminating the list with rdf:nil using the following sequence: If the list has no element, generate a triple using the active subject , active property and rdf:nil . Otherwise, generate a triple using using the active subject , active property and a newly generated BNode identified as first bnode . For each element other than the last element in the list: Create a processor state using the active context, first bnode as the active subject , and rdf:first as the active property . Unless this is the last element in the list, generate a new BNode identified as rest bnode , otherwise use rdf:nil . Generate a new triple using first bnode , rdf:rest and rest bnode . Set first bnode to rest bnode . Otherwise, create a new processor state using copies of the active context , active subject and active property and process the value starting at Step 2 and then proceed using the previous processor state .
  4. If a string is detected, generate detected:
    1. If the active property is the target of a triple using @iri coercion, set the active subject , object by performing IRI Expansion on the string.
    2. Otherwise, if the active property is the target of coercion, set the active object by creating a typed literal using the string and the coercion key as the datatype IRI.
    3. Otherwise, set the active object to a plain literal value created from the string.
    Generate a triple representing the active subject , the active property and the active object .
  5. If a number is detected, generate a typed literal using a string representation of the value with datatype set to either 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 object property and the generated typed literal.
  6. Otherwise, if true or false is detected, generate a triple using the active subject , active object property and a typed literal value created from the string representation of the value with datatype set to xsd:boolean .
8. Best Practices 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. 8.1 JavaScript It is expected that JSON-LD will be used quite a bit in JavaScript environments, however, features like the expanded form for object values mean that using JSON-LD directly in JavaScript may be annoying without a middleware layer such as a simple library that converts JSON-LD markup before JavaScript uses it. One could say that JSON-LD is a good fit for the RDF API, which enables a 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. 8.2 Schema-less Databases 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. MongoDB does not allow the '.' character to be used in key names. This prevents developers from storing IRIs as keys, which also prevents storage of the data in normalized form. While this issue can be avoided by using CURIEs for key values, it is not known if this mechanism is enough to allow JSON-LD to be used in MongoDB in a way that is useful to developers.

9. 6. Advanced Experimental Concepts

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 considered as discussion points; it is merely a list of possibilities where all of the benefits and drawbacks have not been explored.

9.1 Vocabulary Profiles 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", "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/> .

9.2 6.1 Disjoint Graphs

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:

{
  "@": 

  "@coerce": {
    "foaf": "http://xmlns.com/foaf/0.1/"
  },
  "@subject": 

  [
    {
      "@": "http://example.org/people#john",
      "a": "foaf:Person"

      "@subject": "http://example.org/people#john",
      "@type": "foaf:Person"

    },
    {
      "@": "http://example.org/people#jane",
      "a": "foaf:Person"

      "@subject": "http://example.org/people#jane",
      "@type": "foaf:Person"

    }
  ]
}

A disjoint graph could also be expressed like so:

[
  {
    "@": "http://example.org/people#john",
    "a": "foaf:Person"

    "@subject": "http://example.org/people#john",
    "@type": "http://xmlns.com/foaf/0.1/Person"

  },
  {
    "@": "http://example.org/people#jane",
    "a": "foaf:Person"

    "@subject": "http://example.org/people#jane",
    "@type": "http://xmlns.com/foaf/0.1/Person"

  }
]

9.3 6.2 The JSON-LD API Lists

This API provides a clean mechanism that enables developers to convert JSON-LD data into a format that is easier to work with Because graphs do not describe ordering for links between nodes, multi-valued properties in various programming languages. JSON do not provide an ordering of the listed objects. For example, consider the following simple document:

] interface { };
{
...
  "@subject": "http://example.org/people#joebob",
  "foaf:nick": ["joe", "bob", "jaybee"],
...
}

9.3.1 Methods toGraph Parses JSON-LD and transforms

This results in three triples being generated, each relating the data into subject to an Graph, which is compatible individual object, with the RDF Interfaces API specification no inherent order. To address this issue, RDF-based languages, such as [ RDF-INTERFACES TURTLE ]. This method will return null if there are any errors, or if ] use the RDF Interfaces API is not available for use. Parameter Type Nullable Optional Description jsonld concept of an DOMString rdf:List (as described in [ ✘ ✘ The JSON-LD string to parse into the RDFGraph. callback JSONLDParserCallback RDF-SCHEMA ✔ ✔ A callback that is called whenever ]). This uses a processing error occurs on the given JSON-LD string. No exceptions. Return type: Graph toProjection Parses sequence of unlabeled nodes with properties describing a value, a null-terminated next property. Without specific syntactical support, this could be represented in JSON-LD text into an RDF API Projection object as specified by follows:


{
...
  "@subject": "http://example.org/people#joebob",
  "foaf:nick": {,
    "@first": "joe",    "@rest": {      "@first": "bob",      "@rest": {        "@first": "jaybee",        "@rest": "@nil"        }      }    }  },
...
}

As this notation is rather unwieldy and the RDF API specification [ RDF-API ]. If there are any errors, null notion of ordered collections is returned. Parameter Type Nullable Optional Description jsonld DOMString ✘ ✘ The JSON-LD string rather important in data modeling, it is useful to parse into have specific language support. In JSON-LD, a list may be represented using the Projection. template object @list ✔ ✘ The Projection template to use when building keyword as follows:


{
...
  "@subject": "http://example.org/people#joebob",
  "foaf:nick": {"@list": ["joe", "bob", "jaybee"]},
...
}

This describes the Projection. subject DOMString ✔ ✘ The subject to use when building the Projection. callback JSONLDParserCallback ✔ ✔ A callback that of this array as being ordered, and order is called whenever maintained through normalization and RDF conversion. If every use of a processing error occurs on the given JSON-LD string. No exceptions. Return type: object The JSONLDParserCallback multi-valued property is called whenever a processing error occurs on input data. list, this may be abbreviated by adding an @coerce term:

] interface { };
{
  "@context": {
    ...
    "@context": {      "@list": ["foaf:nick"]    }  },
...
  "@subject": "http://example.org/people#joebob",
  "foaf:nick": ["joe", "bob", "jaybee"],
...
}

9.3.2 6.2.1 Methods Expansion

error This callback is invoked whenever an error occurs during processing. Parameter Type Nullable Optional Description error DOMString ✘ ✘ A descriptive error string returned by the processor. No exceptions. Return type: void

TBD.

The following example demonstrates how to convert JSON-LD to a projection that is directly usable in a programming environment: 6.2.2 Normalization

TBD.

// 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 objects 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 object 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. ] interface { };

9.3.3 6.2.3 Methods RDF Conversion

normalize Serializes a language-native object into a normalized JSON-LD string. Normalization is important when performing things like equality comparison and digital signature creation and verification. Parameter Type Nullable Optional Description obj object ✘ ✘ An associative array

To support RDF Conversion of key-value pairs that should be converted to a JSON-LD string. It is assumed that a map already exists for the data. No exceptions. Return type: DOMString The Normalization lists, RDF Conversion Algorithm 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 updated as follows:

  1. Remove 2.4a. If the associative array has a @context @list key and preserve it as the transformation map while running this algorithm. value is an array process the value as a list starting at Step 3a .
  2. For each key 2.7.3. Create a new processor state copies of the active context , active subject and active property .
    1. If the key active property is the target of a CURIE, expand @list coercion, and the CURIE to value is an IRI array, process the value as a list starting at Step 3a .
    2. Otherwise, process the value starting at Step 2 .
    3. Proceed using the transformation map previous processor state .
  3. For
  4. 3a. Generate an RDF List by linking each value If element of the value should be type coerced per list using rdf:first and rdf:next , terminating the transformation map , ensure that it is transformed to list with rdf:nil using the new value. following sequence:
    1. If the value is list has no element, generate a CURIE, expand the CURIE to an IRI triple using the transformation map . active subject , active property and rdf:nil .
    2. If the value is Otherwise, generate a typed literal triple using using the active subject , active property and a newly generated BNode identified as first blank node identifier .
    3. For each element other than the type is last element in the list:
      1. Create a CURIE, expand it to an IRI processor state using the transformation map . When generating active context, first blank node identifier as the final value, use expanded object value form to store all IRIs, typed literals active subject , and plain literal s with language information. rdf:first as the active property .
      2. Output each sorted key-value pair without any extraneous whitespace. If the value is an associative array, perform Unless this algorithm, starting at step #1, recursively on the sub-tree. There should be no nesting in the outputted JSON data. That is, is the top-most last element should be an array. Each item in the array contains a single subject with list, generate a corresponding array of properties in UTF-8 sort order. Any related objects that are complex objects themselves should be given new BNode identified as rest blank node identifier , otherwise use rdf:nil .
      3. Generate a top-level object in the top-level array. new triple using first blank node identifier , rdf:rest and rest blank node identifier .
      4. Note that normalizing named
      5. Set first blank nodes is impossible at present since one would have node identifier to specify a rest blank node naming algorithm. For the time being, you cannot normalize graphs that contain named blank nodes. However, normalizing graphs identifier .

A. Markup Examples

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 contain non-named blank nodes JSON-LD is supported. very flexible in what it can express across different Linked Data approaches.

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", "@coerce": { "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); A.1 RDFa

After the code in the The following example above has executed, the jsonldText value will be (line-breaks added for readability): describes three people with their respective names and homepages.

[{"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"}]

<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>

When normalizing xsd:double values, implementers must ensure An example JSON-LD implementation is described below, however, there are other ways to mark-up this information such that the normalized value context is not repeated.


{
  "@context": { "foaf": "http://xmlns.com/foaf/0.1/"},
  "@subject": [
   {
     "@subject": "_:bnode1",
     "@type": "foaf:Person",
     "foaf:homepage": "http://example.com/bob/",
     "foaf:name": "Bob"
   },
   {
     "@subject": "_:bnode2",
     "@type": "foaf:Person",
     "foaf:homepage": "http://example.com/eve/",
     "foaf:name": "Eve"
   },
   {
     "@subject": "_:bnode3",
     "@type": "foaf:Person",
     "foaf:homepage": "http://example.com/manu/",
     "foaf:name": "Manu"
   }
  ]
}

A.2 Microformats

The following example uses a string. In order simple Microformats hCard example to generate express how the string from a double value, output equivalent to Microformat is represented in JSON-LD.


<div class="vcard">
 <a class="url fn" href="http://tantek.com/">Tantek Çelik</a>
</div>

The representation of the printf("%1.6e", value) function hCard expresses the Microformat terms in C must be used where "%1.6e" is the string formatter context and value is uses them directly for the value url and fn properties. Also note that the Microformat to be converted. 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",
    "@coerce": { "xsd:anyURI": "url" }
  },
  "@subject": "_:bnode1",
  "@type": "vcard",
  "url": "http://tantek.com/",
  "fn": "Tantek Çelik"
}

A.3 Microdata

To convert the The Microdata example below expresses book information as a double value in JavaScript, implementers can use 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 following snippet JSON-LD representation of code: the Microdata information stays true to the desires of the Microdata community to avoid contexts and instead refer to items by their full IRI.

// the variable 'value' below is the JavaScript native double value that is to be converted
(value).toExponential(6).replace(/(e(?:\+|-))([0-9])$/,
'$10$2')

[
  {
    "@subject": "http://purl.oreilly.com/works/45U8QJGZSQKDH8N",
    "@type": "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"]
  },
  {
    "@subject": "http://purl.oreilly.com/products/9780596007683.BOOK",
    "@type": "http://purl.org/vocab/frbr/core#Expression",
    "http://purl.org/dc/terms/type": "http://purl.oreilly.com/product-types/BOOK"
  },
  {
    "@subject": "http://purl.oreilly.com/products/9780596802189.EBOOK",
    "@type": "http://purl.org/vocab/frbr/core#Expression",
    "http://purl.org/dc/terms/type": "http://purl.oreilly.com/product-types/EBOOK"
  }
]

When data needs

A.4 Mashing Up Vocabularies

Developers would also benefit by allowing other vocabularies to be normalized, JSON-LD authors should not use values used automatically with their JSON API. There are over 200 Vocabulary Documents that are going to undergo automatic conversion. This is due to available for use on the lossy nature Web today. Some of xsd:double values. these vocabularies are:

Round-tripping data can be problematic if we mix

You can bite developers. We are currently wondering if having a "coerce validation" phase use these vocabularies in the parsing/normalization phases would be a good idea. It would prevent data round-tripping issues combination, like the one mentioned above. so:

A. The Default Context
{
  "@type": "foaf:Person",
  "foaf:name": "Manu Sporny",
  "foaf:homepage": "http://manu.sporny.org/",
  "sioc:avatar": "http://twitter.com/account/profile_image/manusporny"
}

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 Developers can also specify their own Vocabulary documents by modifying the default active context should not be overwritten by JSON-LD authors. All JSON-LD processors must load the following context in as in-line using the intial context before processing JSON-LD text. @context keyword, like so:

{
  "@context":
  {
    "@vocab": "",
    "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": ["rdf:type", "rdf:rest", "foaf:homepage", "foaf:member"],
      "xsd:integer": "foaf:age"
    }
  }

  "@context": { "myvocab": "http://example.org/myvocab#" },
  "@type": "foaf:Person",
  "foaf:name": "Manu Sporny",
  "foaf:homepage": "http://manu.sporny.org/",
  "sioc:avatar": "http://twitter.com/account/profile_image/manusporny",
  "myvocab:personality": "friendly"

}

The @context 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, which is interpreted as a IRI . In the example above, the myvocab string is replaced with " http://example.org/myvocab# " when it is detected. In the example above, " myvocab:personality " would expand to " http://example.org/myvocab#personality ".

This mechanism is a short-hand for RDF, called a CURIE, and provides developers an unambiguous way to map any JSON value to RDF.

B. A.5 Acknowledgements

The editor editors would like to thank Mark Birbeck, who provided a great deal of the rationale and reasoning initial push behind the JSON-LD work via his work on RDFj, Dave Longley Longley, Dave Lehn and Mike Johnson who reviewed, provided feedback, and performed several implementation on implementations of the specification, and Ian Davis, who created RDF/JSON. Thanks also to Nathan Rixham, Bradley P. Allen 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. Another huge thank you goes out to Dave Longley who designed many of the algorithms used in this specification, including the normalization algorithm which was a monumentally difficult design challenge.

C. B. References

C.1 B.1 Normative references

[BCP47]
A. Phillips, M. Davis. Tags for Identifying Languages September 2009. IETF Best Current Practice. URL: http://tools.ietf.org/rfc/bcp/bcp47.txt
[RDF-API] Manu Sporny, Benjamin Adrian, Nathan Rixham; et al. RDF API Latest. W3C Editor's Draft. URL: http://www.w3.org/2010/02/rdfa/sources/rdf-api/
[RDF-CONCEPTS]
Graham Klyne; Jeremy J. Carroll. Resource Description Framework (RDF): Concepts and Abstract Syntax. 10 February 2004. W3C Recommendation. URL: http://www.w3.org/TR/2004/REC-rdf-concepts-20040210
[RDF-INTERFACES]
[RFC3986]
Nathan Rixham, Manu Sporny, Benjamin Adrian; et al. T. Berners-Lee; R. Fielding; L. Masinter. RDF Interfaces Uniform Resource Identifier (URI): Generic Syntax. Latest. W3C Editor's Draft. January 2005. Internet RFC 3986. URL: http://www.w3.org/2010/02/rdfa/sources/rdf-interfaces/ http://www.ietf.org/rfc/rfc3986.txt
[RFC3987]
M. Dürst; M. Suignard. Internationalized Resource Identifiers (IRIs). January 2005. Internet RFC 3987. URL: http://www.ietf.org/rfc/rfc3987.txt
[RFC4627]
D. Crockford. The application/json Media Type for JavaScript Object Notation (JSON) July 2006. Internet RFC 4627. URL: http://www.ietf.org/rfc/rfc4627.txt
[WEBIDL]
Cameron McCormack. Web IDL. 19 December 2008. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2008/WD-WebIDL-20081219

C.2 B.2 Informative references

[ECMA-262]
ECMAScript Language Specification, Third Edition. December 1999. URL: http://www.ecma-international.org/publications/standards/Ecma-262.htm
[MICRODATA]
Ian Hickson; et al. Microdata 04 March 2010. W3C Working Draft. URL: http://www.w3.org/TR/microdata/
[MICROFORMATS]
Microformats . URL: http://microformats.org
[RDF-SCHEMA]
Dan Brickley; Ramanathan V. Guha. RDF Vocabulary Description Language 1.0: RDF Schema. 10 February 2004. W3C Recommendation. URL: http://www.w3.org/TR/2004/REC-rdf-schema-20040210
[RDFA-CORE]
Shane McCarron; et al. RDFa Core 1.1: Syntax and processing rules for embedding RDF through attributes. 31 March 2011. W3C Working Draft. URL: http://www.w3.org/TR/2011/WD-rdfa-core-20110331
[TURTLE]
David Beckett, Tim Berners-Lee. Turtle: Terse RDF Triple Language. January 2008. W3C Team Submission. URL: http://www.w3.org/TeamSubmission/turtle/