Copyright © 2008–09 Toby Inkster, some rights reserved.
GRDDL | uses XSLT | linked to from namespace documents | (or from XML files directly) | to transform XML | into RDF/XML. |
jsonGRDDL | uses JSONT | linked to from JSON Schemas | (or from JSON files directly) | to transform JSON | into RDF/JSON. |
JSON is an increasingly popular format to return results from RESTful web services. Although many websites provide JSON APIs to access their data, clients wishing to make use of this data need to be custom written for each API, as the data structures differ from site to site.
RDF/JSON takes advantage of RDF concepts to provide a single data format capable of storing virtually any data. However, many JSON APIs simply return a structure closely resembling the application's internal representation of the data — probably a format quite different to RDF. What is desired is a mechanism to translate arbitrary JSON structures into RDF.
JSON is often seen as an alternative to XML, and many XML technologies have been ported to JSON, such as SOAP and Schemas. Thus a natural way to map JSON to RDF would be to port GRDDL to JSON. The jsonGRDDL draft specification attempts to do just that.
This document is a draft, but already fairly stable. There are
no features considered to be "at risk". Future drafts may add
additional methods to the global JSON
object mentioned
in chapter 1, and/or add more global objects which may be used,
such as an XmlHttpRequest
-like object.
Please send feedback to the editor or the JSON schema Google Group.
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC2119].
jsonGRDDL transforms [JSON] to RDF (see [CONCEPTS]) using JsonT transformations, which are referenced at a separate URI from the original JSON object.
A transformation file, suitable for use with jsonGRDDL takes the form:
var transform1 = { ... } ;
var transform2 = { ... } ;
var transform3 = { ... } ;
Such that each transformation conforms to [JSONT], and produces as output a string, conforming to [RDFJSON].
The transformation file may also define various objects, functions and variables used within the transformations.
The transformations should not include any script which assumes that they will be evaluated in a browser context, and should use only standard [ECMASCRIPT] functionality. For example, they should not try to access the document
or window
objects, or attempt any interaction with the user. The transformations must assume the evaluation environment provides a built-in global JSON
object, with the following methods:
JSON.parse(string)
JSON.stringify(object)
JSON.transform(object, transformation)
For testing, an ECMAScript file which provides such functions can be found at <http://buzzword.org.uk/2008/jsonGRDDL/jsonobject>.
JSON transformations can be referenced as so:
http://example.net/path/to/transformations.js#x
where x is the variable name corresponding to the
desired transformation. If the fragment identifier is left out of
the URL, a transformation called _main
is used.
Some sample transformations can be found here:
JSON objects may link directly to a transformation, or use a schema which specifies a transformation. If both are provided, the directly linked transformation takes precedence: it is used and the schema transformation is ignored.
JSON objects can link directly to a jsonGRDDL transformation:
{
"$transformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person" ,
"name" : "Joe Bloggs" ,
"mbox" : "[email protected]"
}
Full, absolute URIs must be used.
A JSON object can use a JSON schema (see [SCHEMA]), where the schema itself links to the jsonGRDDL transformation like this:
{
"$schemaTransformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#People" ,
...
}
Full, absolute URIs must be used.
For details on how a JSON object can indicate its schema, see [SCHEMA].
A $schemaTransformation
link must only be provided on the schema's root object, but $transformation
and $schema
may be used on objects nested within the JSON structure:
{
"title" : "This Document" ,
"authors":
[
{
"$transformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person" ,
"name" : "Joe Bloggs" ,
"mbox" : "[email protected]"
},
{
"$transformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person" ,
"name" : "Jane Doe" ,
"mbox" : "[email protected]"
},
{
"$schema" : { "$ref" : "http://example.de/PersonSchema" } ,
"namen" : "Klaus Schmitt" ,
"mbox" : "[email protected]"
}
]
}
Each transformation builds its own RDF graph. These are separate graphs, but may be merged to yield a single graph; however, implementations must not merge blank nodes from different graphs merely because they are similarly named.
Once a valid transformation has been found for a JSON object, transformations for descendent objects are no longer evaluated. In the following example, the transformation for Jane Doe is not evaluated as it is "blocked" by the higher level transformation for Joe Bloggs.
{
"$transformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person" ,
"name" : "Joe Bloggs" ,
"mbox" : "[email protected]" ,
"knows" :
[
{
"$transformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person" ,
"name" : "Jane Doe" ,
"mbox" : "[email protected]"
}
]
}
For Jane's data to be transformed, the Person transformation used on Joe's data has to be able to deal with the nested data, as the transformation associated with Jane will never be run.
There are several types of file used in this specification. This
section outlines the Internet media types with which they should be
served — that is, the Content-Type
header. Implementations
must ignore files which are not served as
the following types.
application/json
(see [JSONMEDIA]),
but may
use application/x-json
or text/x-json
.application/x-schema+json
,
but may
use application/json
,
application/x-json
or text/x-json
.
Once the JSON Schema Proposal has been fully standardised, a media type
of application/schema+json
is expected to be registered;
processors should offer support for this
in anticipation of its successful registration, but publishers
should not use it until then.application/ecmascript
,
(see [ECMAMEDIA]),
but may
use application/x-javascript
,
application/javascript
,
text/javascript
or text/ecmascript
.It is strongly recommended that implementations send appropriate HTTP Accept headers (see [HTTP]) when making requests for schemas and transformations.
Here is a simple JSON Object representing a person. It links directly to a JsonT transformation:
{
"$transformation" : "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person" ,
"name" : "Joe Bloggs" ,
"mbox" : "[email protected]"
}
The JsonT transformation maps the object to RDF/JSON using FOAF:
var Person =
{
"self" : function(x)
{
var rv =
{
"_:Contact" :
{
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type" :
[{
"type" : "uri" ,
"value" : "http://xmlns.com/foaf/0.1/Person"
}],
"http://xmlns.com/foaf/0.1/name" :
[{
"type" : "literal" ,
"value" : x.name
}],
"http://xmlns.com/foaf/0.1/mbox" :
[{
"type" : "uri" ,
"value" : "mailto:" + x.mbox
}]
}
};
return JSON.stringify(rv, 0, 2);
}
};
The output would be the following RDF/JSON:
{ "_:Contact" : { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" : [{ "type" : "uri" , "value" : "http://xmlns.com/foaf/0.1/Person" }], "http://xmlns.com/foaf/0.1/name" : [{ "type" : "literal" , "value" : "Joe Bloggs" }], "http://xmlns.com/foaf/0.1/mbox" : [{ "type" : "uri" , "value" : "mailto:[email protected]" }] } };
Which is equivalent to the following [TURTLE]:
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:Contact a foaf:Person ; foaf:name "Joe Bloggs" ; foaf:mbox <mailto:[email protected]> .
This example doesn't link to a transformation, but instead to a JSON schema. Using the emerging standards from json-schema.org, this can be used to validate the JSON object. The JSON schema can also offer a link to a JsonT transformation.
{
"$schema" : {"$ref":"http://buzzword.org.uk/2008/jsonGRDDL/schema-sample"} ,
"people" : [
{
"name" : "Joe Bloggs" ,
"mbox" : "[email protected]"
},
{
"name" : "Jane Doe" ,
"mbox" : "[email protected]"
}
]
}
The schema includes a $schemaTransformation
link to the
following transformation, which re-uses the Person transformation from
earlier:
var People =
{
"self" : function(x)
{
var rv = {};
for (var i=0; x.people[i]; i++)
{
var person = JSON.parse(Person.self(x.people[i]));
rv["_:Contact" + i] = person["_:Contact"];
}
return JSON.stringify(rv, 0, 2);
}
};
This results in the following graph being generated:
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:Contact1 a foaf:Person ; foaf:name "Joe Bloggs" ; foaf:mbox <mailto:[email protected]> . _:Contact2 a foaf:Person ; foaf:name "Jane Doe" ; foaf:mbox <mailto:[email protected]> .
jCard 0.1 is a draft being worked on by the Microformats Community for representing contacts in JSON. It specifies a list of property names based on the vCard 3.0 (RFC 2426) standard and hCard.
The following references are normative.
The following references are informative.
application/x-schema+json
in line with JSON Schema Proposal Working Draft.