(one of the InLOC Bindings)

The InLOC JSON-LD Binding

Introduction

This is a provisional binding of InLOC using JSON-LD. To understand this binding, readers need to understand the basics of JSON itself and JSON-LD. For more information about JSON and JSON-LD, see the further reading section below. JSON-LD is a specialization of JSON, where the information is able to be translated into RDF. For InLOC information expressed as JSON-LD, the RDF produced is intended to be close to the Naturalized RDF binding of InLOC.

It should be remembered that the primary purpose of JSON is not to support human readability, but to transfer information between, typically, clients and servers as part of a web service. For this reason, consistency of the format is more important than human readability or conciseness.

A "property" in the InLOC information model is represented in JSON as a key:value pair. The term "property" is used in the context of being a property of an object, and the term "key:value pair" is used when the focus in on the key, the value, or the pair itself.

JSON-LD uses the term IRI ("internationalized resource identifier") rather than URI or URL, so the term "IRI" is used also in this document in preference to "URI" or "URL", unless the context suggests otherwise.

JSON-LD examples

This example is developed from example material in the eCOTOOL project. It shows a representation of a possible Europass Certificate Supplement, based on one that existed.

When run through the JSON Playground converter, using the N-Quads option, this results in

(It is N-Triples rather than N-Quads because there are no named graphs, only the one default graph.)

The JSON-LD context

The JSON-LD context is the section, usually at the start of a JSON-LD document, where the mapping is set out between the JSON keys and the IRIs (URIs, URLs). It will be essentially the same for all InLOC JSON-LD documents, except that keys that are not used need not appear in the context. The context can be presented inline, or as a separate document. If it is done in a separate document, if possible it should be the standard context that explicitly includes all the InLOC properties that need to be given expanded definitions.

The context is less important to the general reader, but implementers do need to understand it.

JSON-LD InLOC context
{
  "@context": 
  {
    "abbr": 
    {
      "@id": "http://purl.org/net/inloc/abbr",
      "@container": "@language"
    },
    "combinationRules": 
    {
      "@id": "http://purl.org/net/inloc/combinationRules",
      "@container": "@language"
    },
    "created": 
    {
      "@id": "http://purl.org/net/inloc/created",
      "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
    },
    "description": 
    {
      "@id": "http://purl.org/net/inloc/description",
      "@container": "@language"
    },
    "issued": 
    {
      "@id": "http://purl.org/net/inloc/issued",
      "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
    },
    "label": 
    {
      "@id": "http://purl.org/net/inloc/label",
      "@container": "@language"
    },
    "modified": 
    {
      "@id": "http://purl.org/net/inloc/modified",
      "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
    },
    "number":
    {
      "@id": "http://purl.org/net/inloc/number",
      "@type": "http://www.w3.org/2001/XMLSchema#decimal" 
    },
    "publisher":
    {
      "@id": "http://purl.org/net/inloc/publisher"
    },
    "rights": 
    {
      "@id": "http://purl.org/net/inloc/rights",
      "@container": "@language"
    },
    "title": 
    {
      "@id": "http://purl.org/net/inloc/title",
      "@container": "@language"
    },
    "validityEnd": 
    {
      "@id": "http://purl.org/net/inloc/validityEnd",
      "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
    },
    "validityStart": 
    {
      "@id": "http://purl.org/net/inloc/validityStart",
      "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
    },
    "hasLOCpart":
    {
      "@id": "http://purl.org/net/inloc/hasLOCpart",
      "@type": "@id"
    },
    "@vocab": "http://purl.org/net/inloc/",    
    "subPropertyOf":
    {
      "@id": "http://www.w3.org/2000/01/rdf-schema#subPropertyOf",
      "@type": "@id"
    },
    "comment": null
  }
}

In the example above, the only one of the relationships that has been shown is the most straightforward one, hasLOCpart. In reality, and in the files below, every InLOC relationship that should have an IRI as object also needs to be included.

There are other several technical things of interest.

  1. The "@vocab" definition at the end maps all unspecified keys onto their correct InLOC IRIs.
  2. The "comment" definition unmaps any properties with "comment" as the key, so that no triples will be generated for these.
  3. The RDFS predicate, "subPropertyOf" is introduced in place of the InLOC type, which could easily be confused with "@type". This illustrates how to specify a property that does not belong to the InLOC vocabulary.
  4. If any other non-InLOC properties are used, they must also be defined explicitly in a @context, otherwise they will appear as if they are InLOC properties, mapped to InLOC IRIs.
    • Alternatively, instead of being defined in the context, a local context including any extra properties can be applied on top of the standard InLOC context – see Examples 28 and 29 of the JSON-LD recommendation.
  5. The important things to be defined for general InLOC purposes are the properties which have a specific datatype, or structure.
    • Properties with "@container": "@language" are the ones that are expressed as language maps.
    • Properties with "@type": "http://www.w3.org/2001/XMLSchema#dateTime" represent date-time values. When represented as RDF, the string value is interpreted as having a date-time datatype.
    • Properties with "@type": "@id" have values that are IRIs (URIs, URLs). If a string value is not obviously an IRI, it will be made into one according to a reasonable set of rules.

As this @context is already quite long, and is even longer with all the relationships included, it is be easier to use the JSON-LD facility to have the context defined remotely. In this case, only one "@context" property need appear. As explained in the JSON-LD spec, Example 50, it is a good idea to use one referenced context in conjunction with a "@graph" property, which enables all the JSON-LD nodes that follow to share the same context. Such an arrangement might start as follows.

JSON-LD InLOC referenced context
{
  "@context": "http://purl.org/net/inloc/attachments/InLOC_context.jsonld",
  "@graph":
  [
    {
      (the LOCstructure expressed as JSON-LD)
    },
    {
      (a LOCdefinition expressed as JSON-LD)
    },
    {
      (another LOCdefinition, etc. etc. ... )
    }
  ]
}

Here is the InLOC context file.

To make the context resilient to future changes, the IRI for the context file will be changed to a purl.org IRI.

JSON-LD structure

A single LOCdefinition may be presented as a JSON-LD object, but any metadata not about the LOCdefinition itself may be cumbersome to represent, requiring repetition of some of the "@context".

In general, because JSON-LD relies on a "@context" to map JSON keys to IRIs, it is more convenient to structure the JSON as an object that has just the properties "@context" and "@graph". The graph contains all the InLOC objects, along with any extra objects giving information about objects represented by non-InLOC IRIs.

LOC structure and LOC definitions

LOCstructure and LOCdefinition objects must have an "@id" property. They may also have a "@language" property, to indicate the main language. However, in any case, all strings that can normally be multilingual must have their language given, through the language map structure.

Both LOCstructure and LOCdefinition are JSON objects using the common InLOC list of direct properties, corresponding to elements in the XML binding, together with compound properties and relationships as used in the Naturalized RDF binding. Each name from the direct properties, compound properties or relationships corresponds to a key in JSON.

LOC structure example

The example below shows a LOCstructure in JSON-LD. The first property listed, the "@context", would only be shown if the LOCstructure were being presented by itself. Otherwise, when the LOCstructure is given as part of the default "@graph" that shares the context, no context would be shown at this point. In the full example file, the LOCstructure is represented as part of the default "@graph", and therefore the "@context" does not appear in this place.

The example includes direct properties, compound properties and relationships, which are explained below.

InLOC JSON-LD example: LOCstructure with some optional additional elements
{
  "@context": "attachments/InLOC_context.jsonld",
  "@type": "LOCstructure",
  "@id": "http://www.example.com/abilities/winegrower/1",
  "@language": "en",
  "title":
  {
    "en": "Wine grower (m/f)",
    "de": "Winzer/Winzerin"
  },
  "description":
  {
    "en": "Structure of the skills and competences required for the Final examination in the state-recognized training occupation: Wine grower (m/f)"
  },
  "comment": 
  [
    "note: This is presented as if it were a structure owned by this German agency.",
    "While the content is taken from the document referenced,",
    "it has been created as part of the InLOC project:",
    "see http://purl.org/net/inloc/Home",
    "and is based on work done for the eCOTOOL project:",
    "see http://www.competencetools.eu/"
  ],
  "furtherInformation": "http://www.bibb.de/redaktion/ze/en/winzer_e.pdf",
  "rights":
  {
    "de": "© Bundesagentur für Arbeit",
    "en": "© Federal Employment Agency"
  },
  "created": "2010-08-17T00:00:00",
  "version": "2.0",
  "publisher":
  {
    "@id": "http://www.arbeitsagentur.de/"
  },
  "contributor":
  [
    {
	"label": {"it":"Chiara Carlino"}
    },
    {
	"label": {"en":"Simon Grant"}
    }
  ],
  "level":
  {
    "hasScheme": {
      "@id": "http://www.uis.unesco.org/Education/Pages/international-standard-classification-of-education.aspx",
      "label": {"en":"ISCED 2011"}
    },
    "hasObject": {
      "@id": "http://www.uis.unesco.org/Education/ISCED/2011#35",
      "comment": "this identifier is invented here",
      "label": {"en":"ISCED level 3, Vocational (35)"}
    },
    "number": "3"
  },
  "hasLOCpart":
  [
    "http://www.example.com/abilities/winegrower/109",
    "http://www.example.com/abilities/winegrower/111",
    "http://www.example.com/abilities/winegrower/113",
    "http://www.example.com/abilities/winegrower/115",
    "http://www.example.com/abilities/winegrower/117",
    "http://www.example.com/abilities/winegrower/119",
    "http://www.example.com/abilities/winegrower/121",
    "http://www.example.com/abilities/winegrower/123",
    "http://www.example.com/abilities/winegrower/125",
    "http://www.example.com/abilities/winegrower/127",
    "http://www.example.com/abilities/winegrower/129",
    "http://www.example.com/abilities/winegrower/131",
    "http://www.example.com/abilities/winegrower/133"
  ]
}

Because we have introduced "http://www.arbeitsagentur.de/" as the IRI identifying the publisher, we can then go on to make more statements about that publisher, as in the corresponding XML example:

InLOC JSON-LD example: more details from external IRI
{
  "@id": "http://www.arbeitsagentur.de/",
  "label":
  {
    "en": "Federal Employment Agency",
    "de": "Bundesagentur für Arbeit"
  }
}

This may be the desired approach if, for example, that agency's id was referenced several times, so that the labels would not have to be repeated.

In addition, the InLOC information model, and the XML example related to this one, contains the semantic information that contributor and publisher are sub-properties of by. That is, in the XML, these LOCassociation properties have a type, by. If desired, this can be represented explicitly in JSON-LD as follows.

InLOC JSON-LD example: extra semantic details
{
  "@id": "publisher", 
  "label": {"en": "Publisher"},
  "subPropertyOf": "http://purl.org/net/inloc/by"
},

To avoid confusion with the JSON-LD "@type"" keyword, which is already overloaded, in the JSON-LD binding this uses the equivalent RDFS property, subPropertyOf, which for the above example is defined in the general context.

Alternatively, in the example below, if "subPropertyOf" were not defined in the general context, it could be explicitly placed locally for this node, as follows.

InLOC JSON-LD example: extra semantic details
{
  "@context":
  {
    "subPropertyOf":
    {
      "@id": "http://www.w3.org/2000/01/rdf-schema#subPropertyOf",
      "@type": "@id"
    }
  },
  "@id": "contributor", 
  "subPropertyOf": "http://purl.org/net/inloc/by"
}

Direct properties

Starting with the literal direct properties, in this list the corresponding multiplicity and value type is given after the colon (':'). As properties in a JSON object are unordered, this list is given in alphabetical order of key, which is different from the order in the XML binding.

  • "abbr": single - language map
  • "created": single, date-time
  • "description": single - language map
  • "extraID": multiple - array of string
  • "furtherInformation": multiple - one, or array of more than one of:
    • a string value – typically html, suitably escaped for JSON, or could be a bare URL;
    • a JSON object with properties as described below.
  • "issued": single - date-time
  • "modified": multiple - array of date-time
  • "rights": single - language map
  • "title": single - language map
  • "validityStart": single - date-time
  • "validityEnd": single - date-time
  • "version": single - string (token in XML binding)

Single human-readable values are represented as a "language map", each object having a two-letter language code as key (the same code as the xml:lang attribute in the XML binding) and a value of the actual string. This means that every string object that can have a language must have a language key.

Multiple values are represented using one JSON array containing each of the multiple values.

Using language maps requires an extra restriction compared with the XML binding. For human-readable strings where there is no xml:lang attribute in the XML, the value for the JSON binding will be the value of the default language, which will be given in all cases where there are appropriate strings with no xml:lang attribute. That is, all language-variable strings must have the language attached to them, and not rely on a default language defined for the LOCstructure.

A LOCstructure may have one other optional property:

A LOCstructure may have one key for any of the InLOC relationships. The hasLOCpart key is the most straightforward of these, and is likely to be the most common. The value in each case is either a single IRI or an array of IRIs. These IRIs will normally appear in the same graph, most commonly as separate LOCdefinitions.

A LOCdefinition may have one additional optional property:

Further information

Further information has several options for JSON-LD representation. Because there is no restriction on the number of furtherInformation properties in the same language, a language map cannot be used. The obvious options for furtherInformation in JSON-LD are as follows.

  1. Plain string values. These will not, however, have a language associated with them. To be used either singly, or as an array. A plain string value could be used for a URL of a web page or document.
  2. String values with language: for this, use properties:
    • "@value": the JSON string giving the further information
    • "@language": language code
    • note, however, that there is no easy way of telling whether or not two furtherInformation properties represent the same information in different languages.
  3. Object with IRI: for this, use object with at least the property:
    • "@id" (note that in this case, this does not map to InLOC id).
    • other properties of an object with IRI can be added to this, but not "@value"

Currently there is no defined a way of having furtherInformation as a string value with extra attributes, as is possible in the XML binding.

LOC definition example with furtherInformation

As with the example LOCstructure above, the "@context" would only be shown here if this LOCdefinition were being represented independently. Alternatively, as in the complete JSON-LD example file, the LOCdefinition can appear as part of the default "@graph", sharing the context with the LOCstructure and the other definitions, and therefore the "@context" would not appear here.

InLOC JSON-LD example: LOCdefinition with further information
{
  "@context": "http://purl.org/net/inloc/attachments/InLOC_context.jsonld",
  "@id": "http://www.example.com/abilities/winegrower/123",
  "@type": "LOCdefinition",
  "description":
  {
    "en":"Fill, label and pack wine",
    "it": "Riempire, etichettare e impacchettare il vino"
  },
  "furtherInformation": 
  [
    {
      "@language": "en",
      "@value":"\n<div><p>Filling, labelling and packing wine may involve operating relevant specialist machinery.<\/p>\n<ul>\n<li>For large wine producers, the process will be largely automated, and the competence will involve extensive knowledge of the operation of the automatic machinery.<\/li>\n<li>For small wine producers, each process may be separate and done manually, either by one person or by a team working together.<\/li>\n<\/ul>\n<p>In all cases, a person with this overall competence will take responsibility for ensuring that the wine is correctly labelled, and the labels on the wine corresponds to the label on the packs; and for ensuring that the whole process complies with relevant health and safety and trading standards regulations.<\/p>\n<\/div>\n"
    },
    {
      "@language": "it",
      "@value": "Riempire, etichettare e impacchettare il vino può richiedere l'uso di macchinari specialistici. Per produttori di vino su larga scala, il progesso sarà in gran parte automatizzato e la competenza includerà un'ampia conoscenza dell'operatività dei macchinari. Per piccoli produttori, ogni processo potrebbe essere separato e compiuto manualmente, da una persona o da una squadra. In ogni caso, una persona con questa competenza complessiva avrà la responsabilità di assicurarsi che il vino sia correttamente etichettato e che le etichette sul vino corrispondano a quelle sui pacchi; sarà inoltre responsabile di assicurarsi che l'intero processo si svolga in osservazione dei regolamenti standard di sicurezza salute e commercio."
    },
    {
      "@language": "en",
      "@value": "There is no restriction on having multiple further information elements in the same language, but in this model, no extra attributes are allowed. To have extra attributes would need a more complex graph."
    }
  ]
}

LOC associations, compound properties and relationships

Information that is dealt with in XML through the LOCassociation structure is dealt with differently in RDF, and the aim for JSON-LD is to create a binding that converts into RDF directly, rather than keeping closer to the XML binding.

The properties in the above example with keys "publisher", "contributor", "level" and "hasLOCpart" are types of LOCassociation. Here, the full picture is given of how to represent all LOCassociation types in JSON-LD.

In the InLOC information model, and the XML binding, the LOCassociation structure in outline is as follows.

The InLOC LOCassociation information model

LOCassociation

This original InLOC information model for LOCassociation was intentionally a hold-all structure, which was very good for a concise XSD, but not ideal for representing as linked data. The JSON-LD binding follows the slight rearrangement of this information model for naturalised RDF, in which the different types of LOCassociation are treated differently.

Representing the LOCassociation properties in JSON-LD

Looking first from the point of view of the InLOC information model:

  • the id of the LOCassociation is never represented in JSON-LD;
  • the type of the LOCassociation is either the name of the property itself (for category, credit, level and topic) or is one of the specified scheme ids, where the type is LOCrel or by;
  • the subject is never needed in JSON-LD, as the subject is the "@id" of the current object (or "node") – that is, the LOCstructure or LOCdefinition currently being described;
  • the scheme is only needed for cases with category, credit, level or topic properties –
    • in these cases, the property value is an anonymous object with properties "hasScheme", "hasObject" and, where needed, "number";
  • the object is, in cases other than the ones immediately above, represented directly as a JSON object which is the value of any LOCrel or by property –
    • the LOCrel types of property are defined as having IRI values, so the IRI can be given directly as the JSON property value;
    • by types of property need to have an object as the property value, with at least one of "@id" and "label";
  • where LOCrel types of property need a number (specifically with hasDefinedLevel), the number will appear directly as a property of the subject, as it does in the naturalized RDF binding.

Representing types of LOCassociation in JSON-LD

Turning this round, for another take on the same ideas, here the different LOCassociation types are considered separately.

  1. LOCrel types of association are either structural or associative. The structural InLOC relationships, like hasLOCpart, are represented as straightforward properties of LOCstructure or LOCdefinition, with the name of the relationship as the JSON key and the JSON value as simply the IRI of the LOCdefinition or LOCstructure. In the InLOC JSON-LD "@context", every LOCrel relationship is defined as having type "@id", so the IRI can be simply given as the property value.
    For associative relationships, such as closeMatch, the object may not be a LOCstructure or LOCdefinition, and may or may not have an IRI. In these cases, the property value can be represented as a JSON object, which can have the properties "@label" and/or "@id", thus covering what is in the InLOC information model.
  2. InLOC specifies four by type compound properties: contributor; creator; publisher; and rightsHolder. As these are properly defined, these associations can be represented in RDF and in JSON-LD using the property name as the JSON key. These are structured similarly to associative relationships, as described above.
  3. The other four types of compound properties are handled very similarly. Here, the power of the original InLOC information model is needed. The property key is the name of the type itself: "category"; "credit"; "level"; or "topic". The value is an anonymous JSON-LD object, with properties
    • "hasScheme",
    • "hasObject", and if required,
    • "number".
      The hasScheme and hasObject properties have values that are again anonymous objects, with properties
    • "@id"
    • "label"
      again completing the coverage of the InLOC information model.

More examples of LOCdefinitions with LOCassociations

Examples of LOCrel, by, and level associations have been worked into the examples above. Here follow two examples corresponding to the XML example material, the first a category and the second a topic.

In these examples, the "@context" is not given, because it is assumed that these LOCdefinitions appear all together with the LOCstructure in the default "@graph", thus sharing the "@context" that appears at the top of the file.

InLOC JSON-LD Example of a LOCdefinition with category association
{
  "@id": "http://www.example.com/abilities/winegrower/111",
  "@type": "LOCdefinition",
  "description": {"en":"Make wine using oenological processes"},
  "category":
  [
    {
      "hasScheme":
      {
        "@id": "http://en.wikipedia.org/wiki/Statistical_Classification_of_Economic_Activities_in_the_European_Community",
        "label": {"en":"NACE"}
      },
      "hasObject":
      {
        "extraID": "11.02",
        "label": {"en":"Manufacture of wine from grape"}
      }
    },
    {
      "hasScheme": 
      {
        "@id": "http://aims.fao.org/aos/agrovoc/c_7644",
        "label": {"en": "AGROVOC technology"}
      },
      "hasObject":
      {
        "@id": "http://aims.fao.org/aos/agrovoc/c_8405",
        "label": {"en":"Winemaking"}
      }
    }
  ]
}
InLOC JSON-LD Example of a LOCdefinition with topic association
{
  "@id": "http://www.example.com/abilities/winegrower/115",
  "@type": "LOCdefinition",
  "description": {"en":"Handle and maintain machinery, plants and company equipment and be aware of and assess processes"},
  "topic":
  {
    "hasScheme":
    {
      "@id": "http://aims.fao.org/aos/agrovoc/c_330919",
      "label": {"en":"AGROVOC objects"}
    },
    "hasObject":
    {
      "@id": "http://aims.fao.org/aos/agrovoc/c_25770",
      "label": {"en":"Winemaking equipment"}
    }
  }
}

Representing strings and languages in JSON-LD

There are strict rules for representing strings in JSON. See e.g. RFC 4627. In particular, new lines and carriage returns must be escaped, so that a string in JSON cannot be split across several lines. Thus it is not an ideal format for human reading.

For potentially multilingual strings, as illustrated and explained in the examples above, this JSON binding is more restrictive than the XML binding. In general, equivalent strings in more than one language are represented by a language map, in which each string has its language specified.

  • The string to display in any situation should be:
    1. if the language map has only one key:value pair, then that string value;
    2. or if there is more than one key:value pair, then
      1. the string corresponding to the desired language; or if this is not present
      2. the string corresponding to the default language, if defined; or
      3. any of the strings in the language map.

It is hoped that the correspondence between all of these structures and the structures in the naturalized RDF binding are apparent.

Further reading

JSON-LD:

Basic JSON information:

JSON Schema:

Other JSON schema implementations to link with inLOC:

XML to JSON conversion: