Copyright © 2008–10 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/JSON. What is desired is a mechanism to translate arbitrary JSON data into RDF/JSON, so that developers can apply the rich set of RDF tools (triple stores, query engines, etc) to JSON data.
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. Some parts of
this draft rely on JSON Schema, which is still a draft itself and
subject to change. Future versions may allow HTTP Link
headers that contain a fragment identifier in the anchor
parameter, and provide guidance on how to resolve that fragment
identifier to an object nested inside the JSON data.
Please send feedback to the editor or the JSON schema Google Group.
anchor
ParameterThe 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 [JSON] instances to RDF graphs [CONCEPTS].
A parser encountering a JSON instance discovers the URI of an appropriate JsonT transformation [JSONT], and applies this to the original instance data, yielding an RDF/JSON [RDFJSON] document which it can handle as it sees fit.
The semantics of RDF, of JSON Schemas, and of HTTP Link headers each support the notion of a typed link. In RDF terms, it's the predicate of a triple where the subject and object are resources with URIs. In terms of JSON Schemas and the HTTP link header, it's a link with a rel value, where the rel value itself is a URI.
The transformation URI is discovered by following a typed link from the JSON instance: either a direct link to the transformation; or a link to a schema, which in turn links to a transformation designed to operate on instances of the schema. These two methods of linking from a JSON instance resource to the transformation resource are shown in the illustration below.
The link types between the different resources are grounded in URIs (further defined in § 5):
A JSON instance may be associated with zero or more transformations; 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.
Web Linking [HTTPLINK] provides a mechanism for encoding links as HTTP headers. HTTP-capable jsonGRDDL agents must check HTTP headers for appropriate links.
The following example HTTP response contains two embedded links: both a direct link to a transformation; and a link to a schema which should be followed to find out if it links to a schema transformation. (Note that rel=describedby is used rather than the full URI for that term - this shortcut MUST NOT be used for URIs unless they begin with http://www.iana.org/assignments/link-relations/.)
HTTP/1.1 200 OK Content-Type: application/json Content-Length: 245 Link: </path/to/a/transformation.js>; rel="http://buzzword.org.uk/2008/jsonGRDDL/terms#transformation" Link: <http://example.com/schema.json>; rel=describedby { ... omitted ... }
The following example shows a link from a schema to two schema transformations.
HTTP/1.1 200 OK Content-Type: application/schema+json Content-Length: 1231 Link: <transformation.js>; rel="http://buzzword.org.uk/2008/jsonGRDDL/terms#schemaTransformation" Link: <transformation2.js>; rel="http://buzzword.org.uk/2008/jsonGRDDL/terms#schemaTransformation" { ... omitted ... }
Note that JSON schema provides a shortcut to set a rel=describedby link as part of the Content-Type header:
HTTP/1.1 200 OK Content-Type: application/json;profile=http://example.com/schema.json Content-Length: 245 { ... omitted ... }
anchor
Parameter
#
The HTTP Link header allows an anchor
parameter
to specify the start point of the link (in RDF terms, its subject). Implementations
of this specification are required to ignore any
HTTP Link headers that contain an anchor
parameter unless
the value of that parameter is a URI reference that resolves to the same URI
as the JSON instance data.
This specification defines some JSON object properties to fulfil the same semantics as the HTTP Link headers in the previous section. These offer some advantages over Link headers, but some disadvantages.
The schemas in § 5 formally define these properties in terms of the relationship URIs (link types).
To link from JSON instance data to a transformation, use the
$transformation
property.
{
"$transformation": "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#Person",
"name": "Joe Bloggs",
"mbox": "[email protected]"
}
To link from a JSON schema to a schema transformation, use the
$schemaTransformation
property.
{
"$schemaTransformation": "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#People",
...
}
To link from JSON instance data to a schema, use the
$schema
property.
{
"$schema": "http://example.com/schema.json",
...
}
JSON Schema allows for schemas to be given inline, thus allowing the following:
{
"$schema": {
"$schemaTransformation": "http://buzzword.org.uk/2008/jsonGRDDL/jsont-sample#People",
...
},
...
}
This section defines a profile of JsonT suitable for use with jsonGRDDL.
JsonT is a transformation language analogous to XSLT. It's very easy to implement in Javascript/ECMAScript, but essentially impossible to implement in any other language, so it's likely that any JsonT implementation in other languages will embed an ECMAScript interpreter.
jsonGRDDL transformations produce as output a string, conforming to RDF/JSON syntax [RDFJSON].
jsonGRDDL transformations should not assume that
they will be evaluated in an interactive web-browser context, and should use only standard ECMAScript functionality [ECMASCRIPT]. For example, they should not try to access
the document
or window
objects, or attempt any
interaction with the user. jsonGRDDL 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>.
(Transformations are not required to use this built-in global object, but still need to be aware of its existance as they may need to avoid using, say, a variable called JSON.)
The transformation file may define additional objects, functions and variables to be used within the transformations.
jsonGRDDL transformations should assume they are being evaluated in an environment that supports at least ECMAScript 3.
A transformation file, suitable for use with jsonGRDDL takes the form:
var transform1 = { ... } ;
var transform2 = { ... } ;
var transform3 = { ... } ;
Individual transformations within the script can be referenced using a URI fragment identifier as follows:
http://example.net/path/to/transformations.js#x
where x is the global variable name corresponding to the
desired transformation. If the fragment identifier is left out of
the URL, a global variable called _main
is assumed.
Some sample transformations can be found here:
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
,
but may
use application/x-json
or text/x-json
[JSONMEDIA].application/schema+json
,
but may
use application/json
,
application/x-json
or text/x-json
[SCHEMA].application/ecmascript
,
but may
use application/javascript
,
text/javascript
or text/ecmascript
[ECMAMEDIA].It is strongly recommended that implementations send appropriate HTTP Accept headers [HTTP] when making requests for schemas and transformations.
{ "extends" : {"$ref" : "http://json-schema.org/hyper-schema#"}, "properties" : { "$transformation" : { "type" : "string", "optional" : true, "title" : "transformation", "description" : "a link to a jsonGRDDL transformation that may be applied to this data", "format" : "uri" } }, "links" : [{ "rel" : "http://buzzword.org.uk/2008/jsonGRDDL/terms#transformation", "href" : "{$transformation}" }] }
A stand-alone copy of the above schema is available at http://buzzword.org.uk/2008/jsonGRDDL/transformation.schema. JSON instance data that uses '$transformation' to link to transformation directly may link to the stand-alone version:
Link: <http://buzzword.org.uk/2008/jsonGRDDL/transformation.schema>, rel="describedby"
{ "extends" : {"$ref" : "http://json-schema.org/hyper-schema#"}, "properties" : { "$schemaTransformation" : { "type" : "string", "optional" : true, "title" : "schema transformation", "description" : "a link to a jsonGRDDL transformation that may be applied to instances of this schema", "format" : "uri" } }, "links" : [{ "rel" : "http://buzzword.org.uk/2008/jsonGRDDL/terms#schemaTransformation", "href" : "{$schemaTransformation}" }] }
A stand-alone copy of the above schema is available at http://buzzword.org.uk/2008/jsonGRDDL/schemaTransformation.schema. JSON schemas that use '$schemaTransformation' to provide indirect transformation links may link to the stand-alone version:
Link: <http://buzzword.org.uk/2008/jsonGRDDL/schemaTransformation.schema>, rel="describedby"
An RDF schema for terms related to jsonGRDDL is shown below in Turtle [TURTLE].
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix : <http://buzzword.org.uk/2008/jsonGRDDL/terms#> . @prefix grddl: <http://www.w3.org/2003/g/data-view> . :Instance a rdfs:Class ; rdfs:label "Instance"@en ; rdfs:subClassOf <http://ontologi.es/lang/data-languages#JSON> ; rdfs:subClassOf grddl:InformationResource ; :Schema a rdfs:Class ; rdfs:label "Schema"@en ; rdfs:subClassOf <http://ontologi.es/lang/data-languages#JSON> ; rdfs:seeAlso <http://tools.ietf.org/id/draft-zyp-json-schema-02.txt> . :Transformation a rdfs:Class ; rdfs:label "Transformation"@en ; rdfs:comment "A JsonT transformation which outputs an RDF/JSON string."@en . :TransformationProperty a rdfs:Class ; rdfs:label "Transformation Property"@en . :transformation a rdf:Property ; rdfs:label "transformation"@en ; rdfs:comment "A link from a JSON instance resource to a transformation resource capable of transforming it into RDF/JSON."@en ; rdfs:domain :Instance ; rdfs:range :Transformation . <http://www.iana.org/assignments/link-relations/describedby> a rdf:Property ; rdfs:label "described by"@en . :schemaTransformation a rdf:Property ; rdfs:label "schema transformation"@en ; rdfs:comment "A link from a JSON schema resource to a transformation resource capable of transforming instances that conform to the schema into RDF/JSON."@en ; rdfs:domain :Schema ; rdfs:range :Transformation . :transformationProperty a rdf:Property ; rdfs:domain :Transformation ; rdfs:range :TransformationProperty .
Here is a simple JSON instance 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 [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.
HTTP/1.1 200 OK
Content-Type: application/json;profile=http://buzzword.org.uk/2008/jsonGRDDL/schema-sample
[
{
"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[i]; i++)
{
var person = JSON.parse(Person.self(x[i]));
rv["_:Contact" + i] = person["_:Contact"];
}
return JSON.stringify(rv, 0, 2);
}
};
This results in the following graph (shown in Turtle) 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.
Kris Zyp pointed me towards JsonT, so that I didn't reinvent the wheel and define my own JSON transformation format.
The members of [email protected] have provided valuable feedback.
application/x-schema+json
in line with JSON Schema Proposal Working Draft.
application/schema+json
to serve schemas.