Serializing SPARQL Query Results in JSON

Editor:Kendall Grant Clark, <kendall@monkeyfist.com>, UMD Mindswap
Editor:Lee Feigenbaum, <feigenbl@us.ibm.com>, IBM
Editor:Elias Torres, <eliast@us.ibm.com>, IBM
Version: alt-ser-sparql.rst,v 1.3 2006/02/16 16:03:08 k Exp
URL:http://mindswap.org/~kendall/sparql-results-json/

The W3C's RDF Data Access Working Group (DAWG) is completing work on a query language for RDF (SPARQL), a data access protocol for conveying queries and query results (SPARQL Protocol for RDF), and an XML format to represent the variable binding results of queries (SPARQL Query Results XML Format). This document describes a format for representing variable binding and boolean results of SPARQL queries using JSON.

Table of Contents

1   Abstract

SPARQL is a query language for RDF developed by the W3C's RDF Data Access Working Group. Included in that work is an XML vocabulary for serializing the results of two SPARQL query forms, SELECT and ASK. This document defines an alternative means of serializing the results of those SPARQL query forms using JSON, a lightweight representation format which emphasizes concision and legibility.

2   Audience

This document is intended for use by anyone with an interest in an alternative to SPARQL Query Results XML Format; and, in particular, to developers who are using AJAX and related models to interact with SPARQL Protocol services.

3   Serializing SPARQL Query Results with JSON

SPARQL variable binding and boolean query results are serialized in JSON in the following ways.

3.1   Document Element

The Document Element is represented as a JSON Object.

XML:

<sparql xmlns="http://www.w3.org/2005/sparql-results#">
 ...
</sparql></pre>

JSON:

{...}

3.2   Header

The Header is represented as a member (key-value pair) in the document element JSON Object, where the key is a string head and where the value is a JSON Object containing a member, the key of which is a string vars and the value of which is a JSON array:

XML:

<head>...</head>

JSON:

'head': {'vars': [...]}

The vars member array contains a sequence of strings, which represent "the set of Query Variable names in the Solution Sequence" [SQRXF]. That is, for each Query Variable name in the Solution Sequence, there is one string element in the vars array with the variable name as the element string.

XML:

<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">

<head>
  <variable name="x"/>
  <variable name="hpage"/>
  <variable name="name"/>
  <variable name="mbox"/>
  <variable name="blurb"/>
</head>
 ...
</sparql>

JSON:

{
  "head": { "vars": [
          "x",
          "hpage",
          "name",
          "mbox",
          "age",
          "blurb",
          "friend"
          ]
 }...

The same order constraints described in [SQRXF] apply to the JSON format described here. The order of variable names in the vars array must be the same as "the order of the variable names given to the argument of the SELECT statement in the SPARQL query" [SQRXF]. Further, "[i]f SELECT * is used, the order of the names is undefined" [SQRXF]. Finally, the order of elements in the vars array "must be the same as that used" [SQRXF]_in the bindings JSON array described below.

For either boolean or variable binding query results, the head object may also contain another member, the key of which is a string "link" and the value of which is a JSON array. Each element of the link array is a URI represented as a JSON string. These URIs must be absolute.

XML:

<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">

<head>
  ...
  <link href="metadata.rdf"/>
</head>
...
</sparql>

JSON:

{
  "head": {
      "link": [
          "http://www.w3.org/TR/rdf-sparql-XMLres/example.rq"
          ],
      ...
}...

3.3   Results

The Results are serialized as an object member, the key of which is the string results or the string boolean, for variable bindings (SELECT) and boolean (ASK) results respectively. The value of the object member results is a JSON object with three required members: ordered, distinct, bindings. The value of the object member boolean is a JSON boolean value (either true or false).

XML::

<results ordered="false" distinct="false">
  <result>
    ...
  </result>
...
</results>

JSON::

{... 
      'results': {
      'ordered': false, 
      'distinct': false,
      'bindings': [...]
   }
}

3.3.1   Variable Binding Results

The value of the ordered and distinct object members is a JSON boolean (true or false) with the same semantics as described in [SQRXF]. If the value of the ordered object member is true, then the elements of the JSON array bindings "must match the query results order". [SQRXF] Likewise, if the value of the distinct object member is true, then the elements of the JSON array bindings must contain no duplications, i.e., must be distinct.

For "each Query Solution in the query results" a JSON object is added to the bindings array [SQRXF]. Each such object "corresponds to one Query Solution in a result" [SQRXF]. The Query Solution Object has a member where the key matches "each Query Variable that appears in the solution", and these properties are ordered in this JSON object the same as the variable strings in the vars array of the head object member. The Query Solution Object properties point to objects that "record how the query variables bind to RDF Terms" [SQRXF].

The following list shows the serialization of various RDF Terms in XML and JSON:

RDF URI Reference U

XML: <binding><uri> U </uri><binding>

JSON: 'name' : {'type':'uri', 'value':' U '}

RDF Literal S

XML: <binding><literal> S </literal><binding>

JSON: 'name' : {'type':'literal', 'value':' S '}

RDF Literal S with language L

XML: <binding><literal xml:lang=" L "> S </literal><binding>

JSON: 'name' : {'type':'literal', 'xml:lang':' L ', 'value':' S '}

RDF Typed Literal S with datatype URI D

XML: <binding><literal datatype=" D "> S </literal><binding>

JSON: 'name' : {'type':'typed-literal', 'datatype':' D ', 'value':' S '}

Blank Node label I

XML: <binding><bnode> I </bnode><binding>

JSON: 'name' : {'type':'bnode', 'value':' I '}

No binding

XML: "If, for a particular solution, a variable is unbound, no binding element for that variable is included in the result element" [SQRXF].

JSON: If, for a particular solution, a variable is unbound, no JSON Object for that variable is included in the bindings array.

3.3.2   Boolean Results

A boolean is serialized as an object member, the key of which is the string "boolean". The value of the object member boolean is a JSON boolean value (either true or false).

XML:

<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">

<head>
  ...
</head>
<boolean>true</boolean>
</sparql>

JSON:

{
  "head": ...
  "boolean" : true
}

The vars object member must not be present in head. In the case of boolean results with no link member in head, the value of head may be JSON null or an empty JSON object, {}. Thus, these two forms are equivalent:

3.4   Examples

The following JSON is a serialization of the XML document output.srx; some whitespace has been added for legibility:

{
   "head": {
       "link": [
           "http://www.w3.org/TR/rdf-sparql-XMLres/example.rq"
           ],
       "vars": [
           "x",
           "hpage",
           "name",
           "mbox",
           "age",
           "blurb",
           "friend"
           ]
       },
   "results": {
       "distinct": false,
       "ordered": true,
       "bindings": [
               {
                   "x" : {
                     "type": "bnode",
                     "value": "r1"
                   },

                   "hpage" : {
                     "type": "uri",
                     "value": "http://work.example.org/alice/"
                   },

                   "name" : {
                     "type": "literal",
                     "value": "Alice"
                   },
                   
                   "mbox" : {
                     "type": "literal",
                     "value": ""
                   },

                   "blurb" : {
                     "datatype": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
                     "type": "typed-literal",
                     "value": "<p xmlns=\"http://www.w3.org/1999/xhtml\">My name is <b>alice</b></p>"
                   },

                   "friend" : {
                     "type": "bnode",
                     "value": "r2"
                   }
               },{
                   "x" : {
                     "type": "bnode",
                     "value": "r2"
                   },
                   
                   "hpage" : {
                     "type": "uri",
                     "value": "http://work.example.org/bob/"
                   },
                   
                   "name" : {
                     "type": "literal",
                     "value": "Bob",
                     "xml:lang": "en"
                   },

                   "mbox" : {
                     "type": "uri",
                     "value": "mailto:bob@work.example.org"
                   },

                   "friend" : {
                     "type": "bnode",
                     "value": "r1"
                   }
               }
           ]
       }
   }

3.5   Programmatic Utility

In programming languages with a concise syntax for accessing data structures and their elements, the JSON serialization of SQRXF offers a path-like language for accessing the parts of SPARQL query results. For example, consider the following code fragments:

Python

>>> q = "SELECT ..."
>>> r = sparql.query(q, imt="application/sparql-results+json")
>>> sr = json.read(r)
>>> print sr["head"]["link"] # The array of metadata links:
['http://www.w3.org/TR/rdf-sparql-XMLres/example.rq',
 'http://www.example.com/foo/bar']

>>> print sr["head"]["link"][0:2] # The first two links in the array
['http://www.w3.org/TR/rdf-sparql-XMLres/example.rq',
 'http://www.example.com/foo/bar']

>>> print sr["results"]["distinct"] # Whether results are distinct
False

>>> print sr["results"]["bindings"] # The bindings array
[[{...}, ...],[{...}, ...]]

>>> print sr["head"]["vars"][:-1] # The name of the last variable
'friend'

>>> bindings = sr["results"]["bindings"]
>>> for binding in bindings:
      print binding # a for-loop to print all the bindings
      ...

>>> for binding in bindings:
      for row in binding:
        print row["value"] # a nested for-loop to print binding values
        ...

JavaScript

// The array of metadata links
// returns: http://www.w3.org/TR/rdf-sparql-XMLres/example.rq
alert(sr.head.link); 

// The first link in the array
// returns: http://www.w3.org/TR/rdf-sparql-XMLres/example.rq
alert(sr.head.link[0]);

// Whether results are distinct
// returns: false
alert(sr.results.distinct);

// The bindings array
// [object Object],...,[object Object]
alert(sr.results.bindings);

// The name of the last variable
// returns: friend
alert(sr.head.vars.slice(-1));

var bindings = sr.results.bindings;

// JavaScript  for...in loop iterates
// through the properties of bindings array
// which are [0,1,length-1] as opposed to the
// array item.

for(i in bindings) {
  var binding = bindings[i];
  alert(binding); // a for-loop to print all the bindings
}

// The only difference here (a subtle one) is
// that the iterator variable is n as opposed to r
// n=name, r=row index
for(i in bindings) {
  var binding = bindings[i];
  for(n in binding) {
    alert(binding[n].value); // a nested for-loop to print binding values
  }
}

// Too bad we can't use valueOf or toString()
// to avoid typing .value, if we did we would break
// the non-eval parsers.
alert(bindings[0].hpage.value);

4   Internet Media Type, File Extension, and Macintosh File Type

A draft submission for IMT registration is available for review.

The Internet Media Type/MIME Type for the SPARQL Query Results JSON Format is "application/sparql-results+json". It is recommended that result files have the extension ".srj" (all lowercase) on all platforms. It is recommended that result files stored on Macintosh HFS file systems be given a file type of "TEXT".

5   Implementations

Leigh Dodd's XMLArmyKnife SPARQL Query Service emits JSON serialized XML results for SELECT and ASK query forms.

Benjamin Nowack's ARC collection of lightweight PHP scripts for RDF developers emits several versions of JSON-based formats when serializing results from SELECT and ASK queries.

6   References

[SQRXF](1, 2, 3, 4, 5, 6, 7, 8, 9, 10) SPARQL Query Results Format, http://www.w3.org/TR/rdf-sparql-XMLres/