SSWAP HTTP API


NAME

JSON Syntax

SYNOPSIS

JSON syntax specification for the SSWAP HTTP API

DESCRIPTION

The SSWAP HTTP API is a set of URLs for RESTful web services that convert JSON (Javascript Object Notation) into SSWAP OWL DL RDF/XML graphs. Conversion is according specifications herein, in accordance with standard JSON syntax. The HTTP API is not a generic JSON to OWL converter, though it does cover the majority of OWL using an intuitive application of JSON.


1. Elements common to all JSON documents


Every JSON document begins and ends with a JSON object delimiter of a left and right curly brace:

{

    ...

}


Within that encompassing JSON object are key : value pairs. Keys are always double-quoted strings. JSON does not allow two keys in an object to have the same lexical value. The following keywords may appear at the top level:


    "api" :  "/makePDG" | "/makeRDG" | "/makeRIG" | "/makeRRG" |

             "/makeRQG" | "/makeType" | "/makeProperty" ,

    "cache" : true | false,

    "prefix" : { ... },

    "import" : [ ... ],


"api" is an optional directive that specifies the particular HTTP API to use if the input is POSTed to the root endpoint http://sswap.info/api/.  This allows one to write simple scripts that POST files of different types (e.g., RDGs, types, properties, etc.) to http://sswap.info/api and each will be further directed to the respective API endpoint.  The "api" directive is not needed if POSTing to a specific endpoint (e.g., http://sswap.info/api/makeRDG).


"cache" is an optional directive that instructs our server to use a cache of ontological terms (true) or to dereference every term for its definition when a term is referenced (false). The default is true. For general use, cache should be either not specified or set to true. For development, for example when one is revising ontology definitions on a web server during active RDG or ontology development, it can be useful to set cache to false, in which case revised term definitions will be used as they are immediately available.  Setting cache to false may incur a network latency performance cost.


"prefix" defines the namespace prefixes to be used in the current and generated documents. Prefixes are used as abbreviators for URIs. The value for the "prefix" keyword must be a JSON object { } whose keys are namespace prefixes (strings) and values are namespace URIs (also strings).  Example:


"prefix" : {

    "aPrefix" : "http://<someSite>/someOntology/",

           "" : "http://<someSite>/myOntology/"

},


A subsequent occurrence of aPrefix:term1 in the document is interpreted as http://<someSite>/someOntology/term1. The combination of a prefix and a local part is called a QName. Note how SSWAP often uses a forward slash (/) at the end of a prefix value to allow per term dereferencing (terms may be dereferenced independent of their full ontologies).


An empty string prefix ("") (as above) may be used to define a default namespace. It is used by omitting the prefix when referencing a term; e.g.:


    ":myTerm" : ...


A default namespace is convenient for supporting short query strings for auto-invocation via an HTTP GET (see /makeRIG). Every prefix must be unique and must have a unique URI string value.


The reserved prefix underscore (_) is automatically defined to represent a named "blank node" (as is common in N3) and must not be redefined in the prefix header (see /makeRDG); e.g.:


    "_:myTerm" : ...


A user-defined prefix may be redefined via query string substitution during translation; this is useful for development. For example the command:


    curl -d@aFile.json http://sswap.info/api?aPrefix=http://localhost:8080/


will substitute the value associated with aPrefix with http://localhost:8080/.  This allows one to use prefixes with URLs for final deployment, yet override the values for testing.  Multiple prefix substitutions may be concatenated using the standard '&' delimiter.


"import" defines the owl:imports statements that will appear in the generated document. The value of the "import" keyword must be a JSON array [ ] that contains comma-separated URIs or QNames of ontologies to be imported (each URI is represented as a string). Example:


{

    "prefix" : {

        "aPrefix" : "http://<someSite>/someOntology/",

               "" : "http://<someSite>/myOntology/"

     },


    "imports" : [

        "aPrefix:myOntology.rdf",

        ":myOntology.rdf",

        "http://yetAnotherSite.org/myOntology"

    ]


    ...

}


SSWAP performs on-demand, transaction-time automatic term dereferencing, so "imports" are rarely needed but may be used to ensure that the generated documents are OWL DL ex situ. Imports that result in large files being dereferenced and retrieved are not necessary and are discouraged.


The remaining syntax below follows the motif:


"myPrefix:myTerm" : {

    "aPrefix:aProperty" : aValue,

    ...

}


where  aProperty may be a user-defined property or one from the rdf, rdfs, xsd, owl, or sswap namespaces. These reserved namespaces are always available and should not be defined in the "prefix" header. Not all namespaces are applicable in all contexts. In general, aValue may be a JSON value, including objects, arrays, numbers, and strings. Not all value data types are applicable in all contexts. JSON objects { } may be used in some contexts to represent the OWL concept of a blank node or anonymous class where otherwise a named term is expected.


Arrays [ ] are used as values to assign multiple values to a key, thereby addressing JSON's restriction on non-duplicate keys; e.g.:


"myPrefix:myTerm" {

    "rdfs:comment" : [ "This is one comment", "This is another comment" ]

}


will generate two rdfs:comment statements. (An occurrence of rdfs:comment twice as a key is illegal in JSON).


In the text that follows, we use p: as any user-defined prefix. In repeated occurrence it can be replaced by differing prefixes without loss of generality.


2. Creating a type (/makeType)


A JSON document describing a new type (a named owl:Class) must contain a key that is a URI or QName of the type to be created. By convention, type names begin with a capital letter. The value must be a JSON object, and its keys must either be one of the supported namespace predicates (mentioned below) or a name of a property on which a restriction is to be placed (as described below). Motif:


"p:MyType" : {

    "rdf:type" : someConstruct,

    "rdfs:rdfsProperty" : someConstruct,

    "owl:owlProperty" : someConstruct,

    "p:someProperty" : owlRestriction

}


2.1 Type subsumption: rdfs:subClassOf


This predicate can appear only within a named type definition, and can be used in three ways:


"p:MyType" : {

   "rdfs:subClassOf" : "p:SuperType"

}


or


"p:MyType" : {

   "rdfs:subClassOf" : {

    ... an anonymous type, defined in-line here instead of at a URI

   }

}


or


"p:MyType" : {

   "rdfs:subClassOf" : [

    ... an array (comma-delimited list) of types

   ]

}


In the first case, the super type is a named type (p:SuperType); in the second case, the super type is an anonymous type expression (which should represent an owl:unionOf, owl:intersectionOf, owl:Restriction, or owl:complementOf) as in:


"p:MyType" : {

   "rdfs:subClassOf" : {

        "owl:unionOf" : [ "p:ThisType", "p:ThatType" ]

   }

}


JSON does not allow duplicate keys, so in the third case we use a JSON array to make p:myType a subtype of many types:


"p:MyType" : {

   "rdfs:subClassOf" : [

        "p:SuperType1",

        "p:SuperType2",

        {

        ... an anonymous type, defined in-line here instead of at a URI

        }

   ]

}


2.2 Type equivalency: owl:equivalentClass


Similar to rdfs:subClassOf, this predicate can only be used within a named type definition, and can be used in three ways:


"p:MyType" : {

   "owl:equivalentClass" : "p:ThatType"

}


or


"p:MyType" : {

   "owl:equivalentClass" : {

    ... an anonymous type, defined in-line here instead of at a URI

   }

}


or


"p:MyType" : {

   "owl:equivalentClass" : [

    ... an array (comma-delimited list) of types

   ]

}


2.3 Disjointedness (an individual belong to one type cannot belong the other): owl:disjointWith


Similar to rdfs:subClassOf and owl:equivalentClass, this predicate can only be used within a named type definition, and in three ways:


"p:MyType" : {

   "owl:disjointWith" : "p:ThatType"

}


or


"p:MyType" : {

   "owl:disjointWith" : {

    ... an anonymous type, defined in-line here instead of at a URI

   }

}


or


"p:MyType" : {

   "owl:disjointWith" : [

    ... an array (comma-delimited list) of types

   ]

}


2.4 Set operations: owl:complementOf


Similar to rdfs:subClassOf, owl:equivalentClass, and owl:disjointWith, this predicate can only be used within a named type definition, and in three ways:


"p:MyType" : {

   "owl:complementOf" : "p:ThatType"

}


or


"p:MyType" : {

   "owl:complementOf" : {

    ... an anonymous type, defined in-line here instead of at a URI

   }

}


or


"p:MyType" : {

   "owl:complementOf" : [

    ... an array (comma-delimited list) of types

   ]

}


Using this predicate will make the subject type equivalent to the complement.


2.5 Set operations: owl:intersectionOf


This predicate can be used both within named types and anonymous type expressions. Its value must be an array of type expressions (either named types or anonymous type expressions):


"p:MyType" : {

  "owl:intersectionOf" : [

    "p:ThatType",

    { ... an anonymous type, defined in-line here instead of at a URI }

  ]

}


The API will generate an owl:equivalentClass relation to the intersection, thereby establishing a necessary and sufficient a definition.


2.6 Set operations: owl:unionOf


This predicate can be used both within named types and anonymous type expressions. Its value must be an array of type expressions (either named types or anonymous type expressions):


"p:MyType" : {

  "owl:unionOf" : [

    "p:ThatType",

    { ... an anonymous type, defined in-line here instead of at a URI }

  ]

}


The API will generate an owl:equivalentClass relation to the union, thereby establishing a necessary and sufficient a definition.


2.7 Set operations: owl:oneOf


This predicate can be used both within named types and anonymous type expressions. Its value must be an array of URIs of individuals (not types or type expressions):


"p:MyType" : {

  "owl:oneOf" : [ "p:individual1", "http://.../individual2" ]

}


The relation owl:oneOf "closes the world", so individuals that belong to p:MyType are those, and only those, listed. Non-listed individuals (URI resources) may be considered included in this set as part of inferencing if and only if they are equivalent (owl:sameAs) to a listed individual. In this case, the individual is considered "in the list," but under a different name.


2.8 URI of a property


Any other URI that appears as a key within the type definition is treated as a URI of a property on which an owl:onProperty restriction is being placed. If the URI appears as a key for a named type, the restriction will be added as a super type to that named type. In case of anonymous types, the restriction will be used accordingly to its context. For example:


"p:MyType" : {

  "p:myProperty" : { "owl:cardinality" : 1 }

}


will make an owl:cardinality restriction (see below) on myProperty a super-type of myType. Another example:


"p:MyType" : {

  "owl:intersectionOf" : [

    { "p:thisProperty" : { "owl:cardinality" : 1 } },

    { "p:thatProperty" : { "owl:cardinality" : 1 } }

  ]

}


The example above will generate two owl:cardinality restrictions (one for thisProperty and one for thatProperty), and will place them within the owl:intersectionOf.


With the exception of { "owl:minCardinality" : 0 }, the default, is to generate owl:equivalentClass relations to the implied owl:Restriction class. To force a subsumption relation, use rdfs:subClassOf explicitly; e.g.:


"p:MyType" : {

  "rdfs:subClassOf" : {

    "owl:intersectionOf" : [

      { "p:thisProperty" : { "owl:cardinality" : 1 } },

      { "p:thatProperty" : { "owl:cardinality" : 1 } }

    ]

  }

}


Equivalency to a minimum cardinality of 0 with no maximum cardinality would generate  equivalency to owl:Thing; this is usually not wanted and can be pathological to inference expectations. Thus in this special case a rdfs:subClassOf is generated even if not explicitly stated. Statements employing { "owl:minCardinality" : 0 } are often used to syntactically link a class with a property (e.g., to indicate that a service accepts optional parameters), even though the statement makes no new logical inferences. In other cases, be careful with owl:equivalentClass, as reasoning over it can generate unexpected equivalency to owl:Thing.


The value for each property restriction is a JSON object that can contain the following elements:


2.8.1 Defining types based on cardinality restrictions on properties: owl:cardinality, owl:minCardinality, owl:maxCardinality


Cardinality refers to the number of semantically (not lexically) distinct values that a property must have in order for an individual with that property to be a member of a class. A reserved key word "cardinality" may be used to combine minimum and maximum cardinality restrictions into a single statement. The value of the "cardinality" key is a JSON array with two integer values for the minimum and maximum respectively. If the values in the array are the same, it generates a single owl:Restriction with a single owl:cardinality predicate. Otherwise, it generates two owl:Restrictions, one for owl:minCardinality and one for owl:maxCardinality. If the minimum cardinality is 0, the respective restriction is not generated (since this is the OWL default).  Note that in OWL there is no way to restrict the number of instances of a property that an individual may have; instead, one restricts the number of semantically distinct values of a property as observed for any given individual.  Examples:


"p:MyType" : {

    "p:property1" : { "owl:cardinality" : 1 },

    "p:property2" : { "cardinality" : [0,1] },

    "p:property3" : { "owl:maxCardinality" : 1 },

    "p:property4" : { "owl:minCardinality" : 2, "owl:maxCardinality" : 5 }

}


The first example sets the cardinality to exactly 1; i.e., there must be exactly one semantically distinct value. The second example sets the maximum cardinality to 1, thereby designating property2 as optional, since 0 is also allowed. The third example is equivalent to the second example. The fourth example is equivalent to { "cardinality" : [2,5] }.


SSWAP uses cardinality to distinguish between required and optional service parameters: properties with a cardinality greater than 0 are required; those including 0 are optional.


2.8.2 Defining types based on the range of a property designating a specific type: owl:allValuesFrom and owl:someValuesFrom


These two keys allow generation of owl:allValuesFrom (the Universal: "for all" ∀) and owl:someValuesFrom (the Existential: "there exists" ∃) restrictions. The existential nature of owl:someValuesFrom implies a minimum cardinality of 1. The value for these keys has to be either a type or an anonymous type expression. Example:


"p:MyType" : {

    "p:thisProperty" : { "owl:allValuesFrom" : "p:ThisType" },

    "p:thatProperty" : {

      "owl:someValuesFrom" : {

        "owl:intersectionOf" : [ ... ]

      }

    }

}


2.8.3 Defining types based on a property having a specific value: owl:hasValue


Types may be defined by examining the value(s) of properties present on individuals. Any individual with at least one instance of the property with the specified value will be considered a member of the type. Examples:


"p:MyType" : {

    "p:someObjectProperty" : {

        "owl:hasValue" : "http://..."

    }

}


or


"p:MyType" : {

    "p:someDatatypeProperty" : {

        "owl:hasValue" : "5"

    }

}


XSD datatyping is supported; e.g., http://...^xsd:anyURI.


2.8.4 Defining types based on the characteristic of a property having its subject as its own object: owl:hasSelf


The recommend value for owl:hasSelf  is "true"^^xsd:boolean (in all cases), thus this key should only be used with "true" (see OWL 2 "Semantic Conditions for the Vocabulary Properties"). Example:


"p:myProperty" : { "owl:hasSelf" : "true" }


3. Creating a property (/makeProperty)


A JSON document describing the new property must contain a key that is a URI or QName of the property being created. By convention, property names begin with a lower case letter. The value must be a JSON object, and object's keys must be one of the supported namespace predicates (mentioned below).  Predicates on properties are always from the rdf, rdfs, or owl namespaces. Motif:


"p:myProperty" : {

    "rdf:type" : someConstruct,

    "rdfs:rdfsProperty" : someConstruct,

    "owl:owlProperty" : someConstruct

}


For properties, the following keys are supported:


3.1 Classifying a property as belonging to exactly one of the two required property types: rdf:type


This key is recommended and should be one of two values: "owl:ObjectProperty" or "owl:DatatypeProperty". Example:


"p:myObjectProperty" : { "rdf:type" : "owl:ObjectProperty" }


or


"p:myDatatypeProperty" : { "rdf:type" : "owl:DatatypeProperty" }


3.2 Property subsumption: rdfs:subPropertyOf


Declares the current property a subproperty of a named property. (Anonymous properties are not supported in OWL). Example:


"p:myProperty" : { "rdfs:subPropertyOf" : "p:superProperty" }


3.3 Global restrictions on a property: rdfs:domain and rdfs:range


Declares the domain or range of the property, respectively. The value may be either a URI of a type or an anonymous type. Example:


"p:myProperty" : {

  "rdfs:domain" : "p:MyType",

  "rdfs:range" : { "owl:unionOf" : [ "p:ThisType", "p:ThatType" ] }

}


The JSON-to-OWL converter will dereference terms, and if the property type (i.e., owl:ObjectProperty or owl:DatatypeProperty) can be determined unambiguously by using a combination of rdf:type, rdfs:subPropertyOf, and/or rdfs:range, then that type will be used.  If the type cannot be determined unambiguously then a error is returned and the user must supply a declaring statement. If the type is over-determined (i.e., both an owl:ObjectProperty and owl:DatatypeProperty) then an error is returned.


3.4 Global restrictions on a property: combining rdfs:range and owl:oneOf


Both object properties and datatype properties can be restricted to a closed set of values:


"p:myProperty" : {

     "rdfs:range" : {

       "owl:oneOf" : [ "p:resource1", "http://.../resource2" ]

      }

}


or


"p:myProperty" : {

     "rdfs:range" : {

       "owl:oneOf" : [ "aLiteral", "anotherLiteral" ]

      }

}


Best practice is to declare the property type explicitly, which allows the use of simple URL strings in either case, e.g.:


"p:myObjectProperty" : {

     "rdf:type" : "owl:ObjectProperty",

     "rdfs:range" : {

       "owl:oneOf" : [ "http://.../resource", ... ]

      }

}


or


"p:myDatatypeProperty" : {

     "rdf:type" : "owl:DatatypeProperty",

     "rdfs:range" : {

       "owl:oneOf" : [ "http://.../resource", ... ]

      }

}


In the former http://.../resource will be interpreted as a resource, while in the latter will be interpreted as a literal of datatype xsd:anyURI. When property types are not explicitly declared, URL string syntax may be used to force property typing by virtue of the values being either resources (using the N3 convention of angle brackets '< >') or XSD datatypes:


"p:myProperty" : {

     "rdfs:range" : {

       "owl:oneOf" : [ "<http://.../resource>", ... ]

      }

}


or


"p:myProperty" : {

     "rdfs:range" : {

       "owl:oneOf" : [ "http://.../resource^^xsd:anyURI", ... ]

      }

}


The former will result in p:myProperty being an owl:ObjectProperty while the latter will result in it being an owl:DatatypeProperty. It is illegal in OWL DL to mix object property values and datatype property values for the same property; this is enforced by the API.


3.5. Global property equivalency and inverse: owl:equivalentProperty and owl:inverseOf


Declares an equivalent property or an inverse property of the subject property. The value must be a URI of a named property. Examples:


"p:myProperty" : { "owl:equivalentProperty" : "p:thisProperty" },

"p:thisProperty" : { "owl:inverseOf" : "p:thatProperty" }


3.6. Global functional and inverse functional properties: owl:FunctionalProperty and owl:InverseFunctionalProperty


A subject with multiple occurrences of a functional property implies that the objects are semantically equivalent (i.e., if p is an owl:FunctionalProperty, then 'A p X' and 'A p Y' implies X = Y). An object as the value of multiple occurrences of an inverse functional property implies that the subjects are semantically equivalent (i.e., if  p is an owl:InverseFunctionalProperty, then 'A p X' and 'B p X' implies that A = B). A property that is both owl:FunctionalProperty and owl:InverseFunctionalProperty implies a "one-to-one and onto" mapping of a unique object for every unique subject. Example:


"p:myProperty" : {

  "rdf:type" : [

    "owl:FunctionalProperty", "owl:InverseFunctionalProperty"

  ]

}


It is illegal in OWL DL for a property that is an owl:DatatypeProperty to be also an owl:InverseFunctionalProperty; this is enforced by the API.


Be advised that these global property statements (like others above) may have unintended consequences: e.g., if property p is an owl:FunctionalProperty and there exist the statements 'A p X' and 'A p Y', then a reasoner will conclude that X = Y, and will generate all consequent statements implied globally across the entire ontology. If p is an owl:DatatypeProperty, then X and Y must be semantically equivalent or the model will be inconsistent; if p is an owl:ObjectProperty, then there must be no inferences that contract this, or the model will be inconsistent. If two individuals are equated as being the same, then each must have the same value for any datatype owl:FunctionalProperty or the model will be inconsistent. Thus errors with functional and inverse functional properties may appear as claims that some functional property has two values, even if the property on any one individual has only "one" explicit value. This is because the reasoner has concluded that two individuals, each with their own instances of a functional property with different values, are "the same" individual. Semantic equivalency differs for datatype and object property values; for discussion the reader should consult a text on OWL.


4. Creating a Resource Graph


Resource graphs (PDG, RDG, RIG, RRG, or RQG) allow annotating "things"--e.g., the resource itself and/or its subjects and objects. Thus the motif is:


"p:myResource" : {

    "rdf:type" : someConstruct,

    "rdfs:rdfsProperty" : someConstruct,

    "owl:owlProperty" : someConstruct,

    "p:someProperty" : someConstrict

}


See /makePDG, /makeRDG, /makeRIG, /makeRRG, and /makeRQG for details.

USAGE NOTES

JSON documents are POSTed to the respective HTTP API URI: /makePDG, /makeRDG, /makeRIG, /makeRRG, /makeRQG, /makeType, or /makeProperty; see those manual pages for specifications on how to engage each service.


Not all OWL classes and properties are listed above, though most of OWL DL and OWL 2 is supported. Parsing on the API is fault-tolerant and silent on recoverable errors. For example, "rdfs:type" is silently ignored (because there is no "type" in the rdfs namespace; the correct QName is "rdf:type"). This can cause unexpected results.

DIAGNOSTICS

Unrecoverable parsing errors on the JSON input or a logical inconsistency rendering the resultant graph non-DL results in an HTTP error code other than '200 OK'.

STANDARDS

Input format is standard JSON, with recognition for the reserved strings. Output format is OWL 2 (DL) RDF/XML.

SEE ALSO

SSWAP Home: sswap.info

SSWAP Wiki: sswap.info/wiki

SSWAP Just-In-Time Ontology Editor: sswap.info/jit

SSWAP Java API: sswap.info/javadocs

SSWAP SDK (Software Development Kit): sswap.info/sdk

JSON: http://json.org

JSON validators: http://www.jslint.com, http://www.jsonlint.com

OWL: http://www.w3.org/TR/owl2-overivew

RDF/XML: http://www.w3.org/TR/REC-rdf-syntax

AUTHORS

Damian Gessler, Blazej Bulka

AVAILABILITY

The software is open source.

JSON Syntax

JSON Syntax