JSON Output Format

Overview

The OpenCalais API has a new output format: JSON. Using this format, users can leverage JavaScript’s inherent support of JSON to simplify processing of OpenCalais responses. There is wide support for JSON in other programming languages as well by using external tools.

If you’ve been using the OpenCalais API’s RDF output format so far, you can rest assured that all required information available to you in the RDF output will be available in the JSON responses as well.

In order to get output in JSON format specify application/json as the output format in the paramxXML parameter in calls to Calais. For example:

<c:params xmlns:c=http://s.opencalais.com/1/pred/ 
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <c:processingDirectives
        c:contentType="text/txt"
        c:outputFormat="application/json">
    </c:processingDirectives>
    <c:userDirectives />
    <c:externalMetadata />
        </c:params>

Note that the above is just an example. You can change the c:contentType parameter above and set additional paramsXML fields if you wish. As long as the c:outputFormat is set to application/json you’ll get a JSON response.

Using JSON: Who and Why?

JSON (JavaScript Object Notation) is often compared to XML, as an alternative format for server responses. JSON’s advantages in this case are:

  • Compactness: the same information is represented by a shorter string in JSON than in XML
  • Simplicity: especially for JavaScript users, processing JSON is simpler than processing XML

If you’re processing responses from OpenCalais within JavaScript code, the new JSON output format is perfect for you. Other languages usually require an external utility to process JSON, and the simplicity of use depends on the specific utility used.

Within JavaScript code, the built-in eval() function converts JSON strings into objects. This function is identical across browsers, unlike the various XML parsers used in different browsers.

Once you convert the JSON string to an object, you can access members in the JSON structure using dot notation. For example, once a JSON string was converted to object x using eval(), you can access x.name to get the value of the name member available in JSON.

Note that calling Calais directly from within JavaScript code may cause other problems, related to the Same Origin Policy of browsers or other issues. Nevertheless, when using JSON, your server can serve as a transparent proxy, that forwards responses from OpenCalais verbatim to your JavaScript client.

JSON Output Test Page

Processing the Response in JavaScript

The JSON response you receive from OpenCalais can be further processed to make it even simpler. The easiest way to use the OpenCalais JSON output in JavaScript code is described in this section.

First, copy and paste these two helper functions into your JavaScript:


function resolveReferences(flatdb) {
      for (var element in flatdb)
            for (var attribute in flatdb[element]) {
                  var val = flatdb[element][attribute];
                  if (typeof val == 'string')
                        if (flatdb[val] != null)
                              flatdb[element][attribute] = flatdb[val];
            }
}
function createHierarchy(flatdb) {
      var hdb = new Object();
      for (var element in flatdb) {
            var elementType = flatdb[element]._type;
            var elementGroup = flatdb[element]._typeGroup;
            if (elementGroup != null) {
                  if (hdb[elementGroup] == null)
                        hdb[elementGroup] = new Object();
                  if (elementType != null) {
                        if (hdb[elementGroup][elementType] == null)
                              hdb[elementGroup][elementType] = new Object();
                        hdb[elementGroup][elementType][element] = flatdb[element];
                  } else
                        hdb[elementGroup][element] = flatdb[element];
            } else
                  hdb[element] = flatdb[element];
      }
      return hdb;
}

Now, let’s assume you have the OpenCalais JSON response within a JavaScript variable called jsonResponse. The following code will produce a simplified object for use:

var jsonObject = null;
var simpleJSON = null;
try
{
    eval('jsonObject = ' + jsonResponse);       
        resolveReferences(jsonObject);
    simpleJSON = createHierarchy(jsonObject);
    // start using simpleJSON
}
catch    (e)
{
         // handle errors
}               

Specification

The simplified JSON object’s structure is as follows:

    "doc": {
        "info": {
            <all fields of DocInfo object taken from CalaisRDF>
        },
        "meta": {
            <all fields of DocInfoMeta object taken  from CalaisRDF>
            "messages": [
                {
                    <all fields of c:message object of DocInfoMeta >
                }
            ]
        }
    },
"topics": {
<URI of DocCat object>: {
"_typeGroup": "topics",
<all fields of this DocCat object taken from CalaisRDF>
  },
  <…other topics…>
    },
"entities": {
<entity type, like “Company”>: {
<URI of entity object>: {
"_type": "Country",
"_typeGroup": "entities",
        <all fields of this entity object taken from CalaisRDF>
"instances": [
            {
<all fields of the respective InstanceInfo of this entity object>
            }
        ],
"relevance": <value of c:relevance field of respective relevance>,
"resolutions": [
            {
<all fields of the respective resolution object of this entity>
            }
        ]
    },
<…other entities of the same type…>
},<…other entity types…>
    },
"relations": {
<relation type, like “ConferenceCall”>: {
<URI of relation object>: {
"_type": "ConferenceCall",
"_typeGroup": "relations",
<all fields of this relation object taken from CalaisRDF>
"instances": [
{
<all fields of the respective InstanceInfo of this relation object>
}
]
}
<…other relations of the same tipe…>
}
<…other relation types…>
    }

The following JSON provides an example of the simplified JSON:

{
    "doc": {
        "info": {
            "document": "<document>...</document>",
            "externalMetadata": "",
            "submitter": "",
            "allowDistribution": "true",
            "allowSearch": "true",
            "calaisRequestID": "53bfd801-0b48-44b8-bfcb-cac7cc690312",
            "externalID": "",
            "id": "http://id.opencalais.com/TUbejyfbRoTIOh7oTkKA2Q"
        },
        "meta": {
            "submitterCode": "d98c1dd4-008f-04b2-e980-0998ecf8427e",
            "signature": "digestalg-1|UYnCz0tzGver5esfcsd5JOZUfF4=|jJsPKDCdta+80FRtjLMC3tK2SQaFQbFMM0u2Eg2sPUQkWj33Br98cg==",
            "contentType": "text/html",
            "emVer": "UnifiedIM-DJ",
            "langIdVer": "DefaultLangId",
            "language": "English",
            "processingVer": "CalaisJob01",
            "submissionDate": "2008-08-24 18:13:52.203",
            "messages": []
        }
    },
    "topics": {
        "http://d.opencalais.com/dochash-1/7b203398-b867-3595-ac40-2c0801e17bb2/cat/1": {
            "_typeGroup": "topics",
            "category": "http://d.opencalais.com/cat/Calais/BusinessFinance",
            "classifierName": "Calais",
            "categoryName": "Business_Finance",
            "score": 0.478
        }
    },
    "entities": {
        "Country": {
            "http://d.opencalais.com/genericHasher-1/398f0f7f-7b2f-3363-bda4-f09b836ed062": {
                "_type": "Country",
                "_typeGroup": "entities",
                "name": "Germany",
                "instances": [
                    {
                        "detection": "[ France and ]Germany[, and also India]",
                        "prefix": " France and ",
                        "exact": "Germany",
                        "suffix": ", and also India",
                        "offset": 5927,
                        "length": 7
                    }
                ],
                "relevance": 0.06,
                "resolutions": [
                    {
                        "name": "Germany",
                        "lat": "51.0",
                        "long": "9.0"
                    }
                ]
            }
        },
        "Company": {
            "http://d.opencalais.com/comphash-1/7f9f8e5d-782c-357a-b6f3-7a5321f92e13": {
                "_type": "Company",
                "_typeGroup": "entities",
                "name": "AT&T",
                "nationality": "N/A",
                "instances": [
                    {
                        "detection": "[been market chatter that Garmin was talking to ]AT&T[ , Reiner said, adding that the only other]",
                        "prefix": "been market chatter that Garmin was talking to ",
                        "exact": "AT&T",
                        "suffix": " , Reiner said, adding that the only other",
                        "offset": 2153,
                        "length": 8
                    }
                ],
                "relevance": 0.272,
                "resolutions": [
                    {
                        "score": 1,
                        "name": "AT&T Corp.",
                        "ticker": "T",
                        "webaddress": "http://www.att.com/"
                    }
                ]
            }
        }
    },
    "relations": {
        "ConferenceCall": {
            "http://d.opencalais.com/genericHasher-1/77723e3f-3683-3497-a13f-71dc4f3a719e": {
                "_type": "ConferenceCall",
                "_typeGroup": "relations",
                "company": <an object reference to company object from entities.Company section with id equals to http://d.opencalais.com/comphash-1/7f9f8e5d-782c-357a-b6f3-7a5321f92e13&...,
                "status": "announced",
                "instances": [
                    {
                        "detection": "[ the United States would have been T-Mobile</p><p>]In the conference call, the company said it[ expects to make carrier announcements in 2009. ]",
                        "prefix": " the United States would have been T-Mobile</p><p>",
                        "exact": "In the conference call, the company said it",
                        "suffix": " expects to make carrier announcements in 2009. ",
                        "offset": 2287,
                        "length": 43
                    }
                ]
            }
        }
    }
}

Sample Code

As an example, once you have the simplified JSON object in a JavaScript variable called simpleJSON, the following code outputs the name of the first identified company along with its relevance.

if (simpleJSON.entities != undefined && simpleJSON.entities.Company != undefined)
{
    var n = 0;
    var first_name = '';
    var first_relevance = 0.0;
    var arr = simpleJSON.entities.Company;
    for(var company in arr)
    {
        if (n == 0)
        {
            first_name = arr[company].name;
            first_relevance = arr[company].relevance;
        }
        n++;
                       
    }
                             
    if (n > 0)
    {
        alert('Found ' + n + ' companies');
        alert('Found first company: ' + first_name +
            ' with relevance ' + first_relevance);
    }
    else
    {
        alert('Did not found any companies');
    }
}

As you can see in the example above, in order to process a specific type of entity, you can find the relevant JSON object in the simplified JSON under entities.<entity type>. If you want to process countries instead, the object is in entities.Country.

The keys of this object are URIs. You can traverse the list of members in entities.Country, for example, and access each country object, as is shown in the for loop of the sample.

For a specific type of relation (event or fact), you can use the same logic on the relations object. For acquisitions the object is in relations.Acquisition.

An important member of each entity or relation is the instances member that corresponds to the RDF description of type InstanceInfo. An example: to find the number of occurrences identified by Calais for a country use: entities.Country[Country_URI].instances.length. In this example Country_URI is the URI for the specific country, which you can find by looping over the entities.Country object.

Always remember to check for the special value undefined before accessing members in order to avoid runtime exceptions.

Processing the Response in Other Languages

If you’re using a language other than JavaScript you have two options:

  • Implement the helper functions presented earlier in that language and use the simplified JSON format as shown above. The difference would be the way to access specific objects and arrays in the JSON, which depends on the interface of the JSON utility that you use.
  • Use the JSON format as it is returned from OpenCalais (called the intermediate format). For technical reasons OpenCalais cannot return the simplified format on its own.

The specification of the intermediate JSON format returned by OpenCalais (i.e., not processed by the helper functions) is:


{
    "doc": {
        "info": {
            <all fields of DocInfo object taken from CalaisRDF>
        },
        "meta": {
            <all fields of DocInfoMeta object taken from CalaisRDF>
            "messages": [
                {
                    <all fields of c:message object of DocInfoMeta >
                }
            ]
        }
    },
    <URI of DocCat object>: {
        "_typeGroup": "topics",
        <all fields of this DocCat object taken from CalaisRDF>
    },
    
    <…other topics…>
    <URI of entity object>: {
        "_type": "Country",
        "_typeGroup": "entities",
        <all fields of this entity object taken from CalaisRDF>
        "instances": [
            {
                <all fields of the respective InstanceInfo of this entity object>
            }
        ],
        "relevance": <value of c:relevance field of respective relevance>,
        "resolutions": [
            {
<all fields of the respective resolution object of this entity>
            }
        ]
    },
    <…other entities…>
    <URI of relation object>: {
        "_type": "ConferenceCall",
        "_typeGroup": "relations",
        <all fields of this relation object taken from CalaisRDF>
        "instances": [
            {
                <all fields of the respective InstanceInfo of this relation object>
            }
        ]
    }
    <…other relations…>
}

The following JSON provides an example of the JSON returned by OpenCalais:

{
    "doc": {
        "info": {
            "document": "<document>...</document>",
            "externalMetadata": "",
            "submitter": "",
            "allowDistribution": "true",
            "allowSearch": "true",
            "calaisRequestID": "53bfd801-0b48-44b8-bfcb-cac7cc690312",
            "externalID": "",
            "id": "http://id.opencalais.com/TUbejyfbRoTIOh7oTkKA2Q"
        },
        "meta": {
            "submitterCode": "d98c1dd4-008f-04b2-e980-0998ecf8427e",
            "signature": "digestalg-1|UYnCz0tzGver5esfcsd5JOZUfF4=|jJsPKDCdta+80FRtjLMC3tK2SQaFQbFMM0u2Eg2sPUQkWj33Br98cg==",
            "contentType": "text/html",
            "emVer": "UnifiedIM-DJ",
            "langIdVer": "DefaultLangId",
            "language": "English",
            "processingVer": "CalaisJob01",
            "submissionDate": "2008-08-24 18:13:52.203",
            "messages": []
        }
    },
    "http://d.opencalais.com/dochash-1/7b203398-b867-3595-ac40-2c0801e17bb2/cat/1":
    {
        "_typeGroup": "topics",
        "category": "http://d.opencalais.com/cat/Calais/BusinessFinance",
        "classifierName": "Calais",
        "categoryName": "Business_Finance",
        "score": 0.478
    },
    "http://d.opencalais.com/genericHasher-1/398f0f7f-7b2f-3363-bda4-f09b836ed062": 
    {
        "_type": "Country",
        "_typeGroup": "entities",
        "name": "Germany",
        "instances": [
            {
                "detection": "[ France and ]Germany[, and also India]",
                "prefix": " France and ",
                "exact": "Germany",
                "suffix": ", and also India",
                "offset": 5927,
                "length": 7
            }
        ],
        "relevance": 0.06,
        "resolutions": [
            {
                "name": "Germany",
                "lat": "51.0",
                "long": "9.0"
            }
        ]
    },
    "http://d.opencalais.com/comphash-1/7f9f8e5d-782c-357a-b6f3-7a5321f92e13": 
    {
        "_type": "Company",
        "_typeGroup": "entities",
        "name": "AT&T",
        "nationality": "N/A",
        "instances": [
            {
                "detection": "[been market chatter that Garmin was talking to ]AT&T[ , Reiner said, adding that the only other]",
                "prefix": "been market chatter that Garmin was talking to ",
                "exact": "AT&T",
                "suffix": " , Reiner said, adding that the only other",
                "offset": 2153,
                "length": 8
            }
        ],
        "relevance": 0.272,
        "resolutions": [
            {
                "score": 1,
                "name": "AT&T Corp.",
                "ticker": "T", 
                "webaddress": "http://www.att.com/"
            }
        ]
    },
    "http://d.opencalais.com/genericHasher-1/77723e3f-3683-3497-a13f-71dc4f3a719e": 
    {
        "_type": "ConferenceCall",
        "_typeGroup": "relations",
        "company": "http://d.opencalais.com/comphash-1/7f9f8e5d-782c-357a-b6f3-7a5321f92e13",
        "status": "announced",
        "instances": [
            {
                "detection": "[ the United States would have been T-Mobile</p><p>]In the conference call, the company said it[ expects to make carrier announcements in 2009. ]",
                "prefix": " the United States would have been T-Mobile</p><p>",
                "exact": "In the conference call, the company said it",
                "suffix": " expects to make carrier announcements in 2009. ",
                "offset": 2287,
                "length": 43
            }
        ]
    }   
}

 

AttachmentSize
TestJSON.html5.48 KB