Publication Date: 2021-01-18
Approval Date: 2020-12-11
Submission Date: 2020-11-06
Reference number of this document: OGC 20-012
Reference URL for this document: http://www.opengis.net/doc/PER/ugas2020
Category: OGC Engineering Report
Editor: Johannes Echterhoff
Title: UML-to-GML Application Schema Pilot (UGAS-2020) Engineering Report
COPYRIGHT
Copyright © 2021 Open Geospatial Consortium. To obtain additional rights of use, visit http://www.opengeospatial.org/
WARNING
This document is not an OGC Standard. This document is an OGC Engineering Report created as a deliverable in an OGC Interoperability Initiative and is not an official position of the OGC membership. It is distributed for review and comment. It is subject to change without notice and may not be referred to as an OGC Standard. Further, any OGC Engineering Report should not be referenced as required or mandatory technology in procurements. However, the discussions in this document could very well lead to the definition of an OGC Standard.
LICENSE AGREEMENT
Permission is hereby granted by the Open Geospatial Consortium, ("Licensor"), free of charge and subject to the terms set forth below, to any person obtaining a copy of this Intellectual Property and any associated documentation, to deal in the Intellectual Property without restriction (except as set forth below), including without limitation the rights to implement, use, copy, modify, merge, publish, distribute, and/or sublicense copies of the Intellectual Property, and to permit persons to whom the Intellectual Property is furnished to do so, provided that all copyright notices on the intellectual property are retained intact and that each person to whom the Intellectual Property is furnished agrees to the terms of this Agreement.
If you modify the Intellectual Property, all copies of the modified Intellectual Property must include, in addition to the above copyright notice, a notice that the Intellectual Property includes modifications that have not been approved or adopted by LICENSOR.
THIS LICENSE IS A COPYRIGHT LICENSE ONLY, AND DOES NOT CONVEY ANY RIGHTS UNDER ANY PATENTS THAT MAY BE IN FORCE ANYWHERE IN THE WORLD. THE INTELLECTUAL PROPERTY IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE DO NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE INTELLECTUAL PROPERTY WILL MEET YOUR REQUIREMENTS OR THAT THE OPERATION OF THE INTELLECTUAL PROPERTY WILL BE UNINTERRUPTED OR ERROR FREE. ANY USE OF THE INTELLECTUAL PROPERTY SHALL BE MADE ENTIRELY AT THE USER’S OWN RISK. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY CONTRIBUTOR OF INTELLECTUAL PROPERTY RIGHTS TO THE INTELLECTUAL PROPERTY BE LIABLE FOR ANY CLAIM, OR ANY DIRECT, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM ANY ALLEGED INFRINGEMENT OR ANY LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR UNDER ANY OTHER LEGAL THEORY, ARISING OUT OF OR IN CONNECTION WITH THE IMPLEMENTATION, USE, COMMERCIALIZATION OR PERFORMANCE OF THIS INTELLECTUAL PROPERTY.
This license is effective until terminated. You may terminate it at any time by destroying the Intellectual Property together with all copies in any form. The license will also terminate if you fail to comply with any term or condition of this Agreement. Except as provided in the following sentence, no such termination of this license shall require the termination of any third party end-user sublicense to the Intellectual Property which is in force as of the date of notice of such termination. In addition, should the Intellectual Property, or the operation of the Intellectual Property, infringe, or in LICENSOR’s sole opinion be likely to infringe, any patent, copyright, trademark or other right of a third party, you agree that LICENSOR, in its sole discretion, may terminate this license without any compensation or liability to you, your licensees or any other party. You agree upon termination of any kind to destroy or cause to be destroyed the Intellectual Property together with all copies in any form, whether held by you or by any third party.
Except as contained in this notice, the name of LICENSOR or of any other holder of a copyright in all or part of the Intellectual Property shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Intellectual Property without prior written authorization of LICENSOR or such copyright holder. LICENSOR is and shall at all times be the sole entity that may authorize you or any third party to use certification marks, trademarks or other special designations to indicate compliance with any LICENSOR standards or specifications.
This Agreement is governed by the laws of the Commonwealth of Massachusetts. The application to this Agreement of the United Nations Convention on Contracts for the International Sale of Goods is hereby expressly excluded. In the event any provision of this Agreement shall be deemed unenforceable, void or invalid, such provision shall be modified so as to make it valid and enforceable, and as so modified the entire Agreement shall remain in full force and effect. No decision, action or inaction by LICENSOR shall be construed to be a waiver of any rights or remedies available to it.
None of the Intellectual Property or underlying information or technology may be downloaded or otherwise exported or reexported in violation of U.S. export laws and regulations. In addition, you are responsible for complying with any local laws in your jurisdiction which may impact your right to import, export or use the Intellectual Property, and you represent that you have complied with any regulations or registration procedures required by applicable law to make this license enforceable.
1. Background
International Organization for Standardization (ISO) 19109:2015 Geographic information – Rules for application schema Clause 2.3 UML application schema, defines a Unified Modeling Language (UML) metaschema for feature-based data. That General Feature Model (GFM) serves as the key underpinning for a family of ISO standards employed by national and international communities to define the structure and content of geospatial data.
OGC 07-036r1 OpenGIS Geography Markup Language (GML) Encoding Standard Annex E UML-to-GML application schema encoding rules, defines a set of encoding rules that may be used to transform a GFM-conformant UML concept model to a corresponding XML Schema (XSD) based on the structure and requirements of GML. The resulting XSD file(s) may be used to define the structure of, and validate the content of, XML instance documents used in the exchange of geospatial data among open-source, commercial, consortia, and government systems. This methodology for deriving technology-specific encodings of GFM-conformant UML concept models based on formalized sets of encoding rules has been successfully applied in other contexts than GML (e.g., technologies based on Resource Description Framework (RDF) encodings) and has come to be generically known as “UGAS.”
ShapeChange (https://shapechange.net/) is an open-source implementation of the UGAS methodology that is regularly employed by the international standards community in the application of ISO standards to the resolution of issues involving data model standardization, content validation, and exchange of geospatial data. The U.S. National System for Geospatial Intelligence (NSG) Application Schema (NAS) standardizes an NSG-wide model for geospatial data that is mission-agnostic and technology-neutral. From it, using Model Driven Architecture (MDA) techniques, technology-tied Platform Specific Models (PSM) may be automatically derived and directly employed in system development. ShapeChange is a key technological underpinning that is heavily employed in development and management of NAS-related technology artifacts.
2. Summary
During UGAS-2020 emerging technology requirements for NAS employment in the NSG, and with general applicability for the wider geospatial community, were investigated and solutions developed in four areas.
-
To enable a wide variety of analytic tradecrafts in the NSG to consistently and interoperably exchange data, the NAS defines an NSG-wide standard UML-based application schema in accordance with the ISO 19109 General Feature Model. In light of continuing technology evolution in the commercial marketplace it is desirable to be able to employ (NAS-conformant) JSON-based data exchanges alongside existing (NAS-conformant) XML-based data exchanges. A prototype design and implementation of UML Application Schema to JSON Schema rules (see the OWS-9 SSI UGAS Conversion Engineering Report) was reviewed and revised based on the final draft IETF JSON Schema standard “draft 2019-09.” The revised implementation was evaluated using NAS Baseline X-3. This work is reported in section UML to JSON Schema Encoding Rule.
-
To maximize cross-community data interoperability the NAS employs conceptual data schemas developed by communities external to the NSG, for example as defined by the ISO 19100-series standards. At the present time there are no defined JSON-based encodings for those conceptual schemas. A JSON-based core profile was developed for key external community conceptual schemas, particularly components of those ISO 19100-series standards used to enable data discovery, access, control, and use in data exchange in general, including in the NSG. This work is reported in section Features Core Profile of Key Community Conceptual Schemas.
The Features Core Profile and its JSON encoding have been specified with a broader scope than the NAS. It builds on the widely used GeoJSON standard and extends it with minimal extensions to support additional concepts that are important for the wider geospatial community and the OGC API standards, including support for solids, coordinate reference systems, and time intervals. These extensions have been kept minimal to keep implementation efforts as low as possible. If there is interest in the OGC membership, the JSON encoding of the Core Profile could be a starting point for a JSON encoding standard for features in the OGC. A new Standards Working Group for a standard OGC Features and Geometries JSON has been proposed.
-
Linked data is increasingly important in enabling “connect the dots” correlation and alignment among diverse, distributed data sources and data repositories. Validation of both data content and link-based data relationships is critical to ensuring that the resulting virtual data assemblage has logical integrity and thus constitutes meaningful information. SHACL, a language for describing and validating RDF graphs, appears to offer significant as yet unrealized potential for enabling robust data validation in a linked-data environment. The results of evaluating that potential – with emphasis on deriving SHACL from a UML-based application schema - are reported in section Using SHACL for Validation of Linked Data.
-
The OpenAPI initiative is gaining traction in the commercial marketplace as a next-generation approach to defining machine-readable specifications for RESTful APIs in web-based environments. The OGC is currently shifting towards interface specifications based on the OpenAPI 3.1 specification. That specification defines both the interface (interactions between the client and service) and the structure of data payloads (content) offered by that service. It is desirable to be able to efficiently model the service interface using UML and then automatically derive the physical expression of that interface (for example, as a JSON file) using Model Driven Engineering (MDE) techniques alongside the derivation of JSON Schema defining data content. A preliminary analysis and design based on the OGC API Features standard, parts 1 and 2, for sections other than for content schemas, is reported in section Generating OpenAPI definitions from an application schema in UML.
All ShapeChange enhancements developed within the UGAS-2020 Pilot have been publicly released as a component of ShapeChange v2.10.0. https://shapechange.net has been updated to document the enhancements.
2.1. Document contributor contact points
All questions regarding this document should be directed to the editor or the contributors:
Contacts
Name | Organization | Role |
---|---|---|
Johannes Echterhoff |
interactive instruments GmbH |
Editor |
Clemens Portele |
interactive instruments GmbH |
Contributor |
2.2. Foreword
Attention is drawn to the possibility that some of the elements of this document may be the subject of patent rights. The Open Geospatial Consortium shall not be held responsible for identifying any or all such patent rights.
Recipients of this document are requested to submit, with their comments, notification of any relevant patent claims or other intellectual property rights of which they may be aware that might be infringed by any implementation of the standard set forth in this document, and to provide supporting documentation.
3. References
The following normative documents are referenced in this document.
-
Internet Engineering Task Force (IETF). RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format [online]. Edited by T. Bray. 2017 [viewed 2020-04-02]. Available at https://tools.ietf.org/html/rfc8259
-
Internet Engineering Task Force (IETF). RFC 7946: The GeoJSON Format [online]. Edited by H. Butler, M. Daly, A. Doyle, S. Gillies, S. Hagen, T. Schaub. 2016 [viewed 2020-04-02]. Available at https://tools.ietf.org/html/rfc7946
-
ISO 8601-2:2019 Date and time — Representations for information interchange — Part 1: Extensions
-
ISO 19109:2015 Geographic information – Rules for application schema
-
Open Geospatial Consortium (OGC). OGC 17-069r3: OGC API - Features - Part 1: Core, Version 1.0.0 [online]. Edited by C. Portele, P. Vretanos. 2019 [viewed 2020-04-02]. Available at http://docs.opengeospatial.org/is/17-069r3/17-069r3.html
-
Open Geospatial Consortium (OGC). OGC 07-036r1: OpenGIS Geography Markup Language (GML) Encoding Standard, Version 3.2.2 [online]. Edited by C. Portele. 2016 [viewed 2020-04-02]. Available at https://portal.opengeospatial.org/files/?artifact_id=74183
-
OpenAPI Initiative (OAI). OpenAPI Specification 3.0 [online]. 2020 [viewed 2020-04-02]. The latest patch version at the time of publication of this standard was 3.0.3, available at http://spec.openapis.org/oas/v3.0.3
4. Terms and definitions
Linked Data is the data format that supports the Semantic Web. The basic rules for Linked Data are defined as:
Use Uniform Resource Identifiers (URIs) to identify things;
Use HTTP URIs so that these things can be referred to and looked up ("dereferenced") by people and user agents;
Provide useful information about the thing when its URI is dereferenced, using standard formats such as RDF/XML; and
Include links to other, related URIs in the exposed data to improve discovery of other related information on the Web.
4.1. Abbreviated terms
API |
Application Programming Interface |
ASCII |
American Standard Code for Information Interchange |
CFP |
Call for Proposals |
CRS |
Coordinate Reference System |
CWA |
Closed-World Assumption |
DASH |
Data Shapes Vocabulary |
DCAT |
Data Catalog Vocabulary |
DDL |
Data Definition Language |
EAP |
Enterprise Architect Project |
ECMA |
European association for standardizing information and communication systems |
EPSG |
European Petroleum Survey Group |
ER |
Engineering Report |
GFM |
General Feature Model |
GML |
Geography Markup Language |
GML-SF |
GML Simple Features |
GRDDL |
Gleaning Resource Descriptions from Dialects of Languages |
GUI |
Graphical User Interface |
HTML |
Hypertext Markup Language |
HTTP |
Hypertext Transfer Protocol |
IETF |
Internet Engineering Task Force |
IP |
Innovation Program |
IRI |
Internationalized Resource Identifier |
ISO |
International Organization for Standardization |
JSON |
JavaScript Object Notation |
JSON-LD |
JSON for Linked Data |
MDA |
Model Driven Architecture |
MDE |
Model Driven Engineering |
MDG |
Model Driven Generation |
MSL |
Mean Sea Level |
NAS |
NSG Application Schema |
NEO |
NSG Enterprise Ontology |
NSG |
U.S. National System for Geospatial Intelligence |
OAI |
OpenAPI Initiative |
OCL |
Object Constraint Language |
OGC |
Open Geospatial Consortium |
OWA |
Open-World Assumption |
OWL |
Web Ontology Language |
POWDER |
Protocol for Web Description Resources |
PSM |
Platform Specific Model |
R2RML |
RDB to RDF Mapping Language |
RDB |
Relational Databases |
RDF |
Resource Description Framework |
RDFS |
RDF Schema |
RDFa |
RDF in Attributes |
RIF |
Rule Interchange Format |
SCXML |
ShapeChange XML |
SHACL |
Shapes Constraint Language |
SKOS |
Simple Knowledge Organization System |
SPARQL |
SPARQL query language for RDF |
SQL |
Structured Query Language |
SSI |
System Security Interoperability |
SWE |
Sensor Web Enablement |
SWG |
Standards Working Group |
SWRL |
Semantic Web Rule Language |
TC |
Technical Committee |
TOSH |
TopBraid Data Shapes Library |
UCUM |
The Unified Code for Units of Measure |
UGAS |
UML to GML Application Schema |
UML |
Unified Modeling Language |
URI |
Uniform Resource Identifier |
URL |
Unform Resource Locator |
W3C |
World Wide Web Consortium |
WGS |
World Geodetic System |
XML |
Extensible Markup Language |
XPath |
XML Path Language |
XQuery |
XML Query Language |
XSD |
XML Schema |
YAML |
YAML Ain’t Markup Language |
4.2. Definitions
-
feature type - A feature type as defined by the General Feature Model (see ISO 19109:2015). In an application schema, a feature type is typically modeled using stereotype <<featureType>>, or a stereotype that maps to that stereotype.
-
object type - An object type is a standard class, instances are plain objects with identify. An object type is not a feature type. In order for ShapeChange to recognize a class as an object type, the class must have no stereotype, or must have stereotype <<type>>, or must have a stereotype that maps to one of these two options.
-
data type - As defined by ISO 19103:2015, section 6.10, a data type is a class with stereotype [dataType] (or a stereotype that maps to that stereotype), which is a set of properties that lacks identity.
5. Overview
This Engineering Report documents results of the UGAS-2020 Pilot. It consists of the following chapters:
5.1. Future work
5.1.1. Extending the JSON Schema Conversion Rules
During UGAS-2020, several ideas for additional conversion rules, or extensions of existing conversion rules, were discussed. The following sections document these ideas. They may be implemented in the future.
5.1.1.1. Encoding the Scale of a Numeric Type
The JSON Schema keyword "multipleOf" can be used to restrict a numeric value to only be valid if division by the keyword’s value (which must be a numeric greater than 0) results in an integer. The keyword could be used to define and validate the scale of a numeric property.
For example, using the type definition: { "type": "number", "multipleOf": 0.01 }
, the values 5, 5.1, and 5.12 would be valid, while value 5.123 would be invalid.
Future work can define a conversion rule to support encoding the scale of a numeric property using the JSON Schema keyword "multipleOf."
5.1.1.2. Union Inheritance
A union type can be converted to JSON Schema in two different ways, as documented in section Union. Currently, inheritance relationships between union types are not supported.
Even though union inheritance has not been used in application schema development thus far, it does not appear to be forbidden by any ISO 19100 standard. However, the semantics of using a union subtype instead of a supertype as a property value are undefined and would need to be established - probably similar to how this would need to be done for inheritance between enumerations and code lists. Because of the lack of a standards-based definition for inheritance of unions, enumerations, and code lists, the conversion of inheritance relationships between unions has not been implemented in UGAS-2020.
However, UGAS-2020 briefly analyzed how union inheritance could be realized. The generalization relationship between a union subtype and its supertype could be realized using the JSON Schema keyword "anyOf", as shown in Listing 1 (using conversion rule rule-json-cls-union-propertyCount to encode the options of each union). This example can be useful for future work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"UnionA": {
"type": "object",
"properties": {
"option1": {
"type": "string"
},
"option2": {
"type": "number"
}
},
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 1
},
"UnionB": {
"anyOf": [
{
"$ref": "#/definitions/UnionA"
},
{
"type": "object",
"properties": {
"option2": {
"type": "string"
},
"option3": {
"type": "number"
}
},
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 1
}
]
}
},
"$ref": "#/definitions/UnionB"
}
These JSON objects are valid against the schema from Listing 1:
1
2
3
4
5
6
7
8
9
{
"option1": "x"
}
{
"option2": "x"
}
{
"option2": 3.1
}
These JSON object are invalid against the schema from Listing 1:
1
2
3
4
5
6
{
"option2": true
}
{
"option3": "x"
}
5.1.1.3. Conversion of OCL Constraints to check JSON data
One of the main goals in UGAS-2020 was to develop UML to JSON Schema conversion rules. A JSON Schema produced using these rules defines a JSON format, for encoding application data in JSON. The JSON Schema can be used to ensure that a given JSON object complies with that format. This is a powerful building block for interoperable web applications, because web applications can now ensure - using JSON Schema validators - that JSON data they exchange actually is compliant with the agreed format.
However, there may be some aspects of the data format that cannot be checked by the JSON Schema, and thus need to be checked by the application itself. One example is that an object which is only encoded by reference in the JSON data actually is one of the allowed types. Another example is data requirements defined by OCL constraints.
In application schema modelling, OCL constraints are used to define requirements that cannot be expressed in UML alone. A full analysis of if and how OCL can be converted to JSON Schema, or if some specification or tool exists, with which OCL expressions can be checked on JSON data, was out-of-scope for UGAS-2020.
Only a particular kind of OCL constraints defined by the NAS, identified as critical for achieving a useful JSON Schema encoding of the NAS, has been investigated in UGAS-2020: constraints that disallow related entity types. For further details, see section Constraints.
Future work may therefore analyse the conversion of OCL constraints to artifacts that can validate the constraint against JSON encoded application schema data.
Note
|
XML Schema based validation also does not cover the aforementioned checks. In general, it is up to the application how the remaining checks are realized. They could be implemented with application specific logic. However, for some checks, additional validation tools may be available. For example, in order to check requirements defined by OCL constraints, Schematron rules can be derived from these constraints, and evaluated against XML encoded data. At the time when this report was written, a similarly powerful tool to perform additional checks on JSON data did not seem to be available. However, there were some developments in that regard (e.g., jsontron), which could be useful starting points for future work on this topic. |
5.1.2. Conversion of JSON data to RDF using JSON-LD
JSON data certainly is of interest to typical web applications. It can also be of interest to the semantic community. With JSON-LD, it is possible to convert JSON data to RDF data. The conversion thereby defines the semantics of the JSON data. The resulting RDF data can be used by semantic applications. The definition of semantics of JSON data through the use of JSON-LD has been investigated in OGC Testbed-14. For further details, also on limitations of that approach, see the OGC Testbed-14: Application Schemas and JSON Technologies Engineering Report.
UGAS-2020 investigated the implications of a few JSON Schema conversion rules regarding the ability for mapping JSON data (that complies to these rules) to RDF using JSON-LD. It is recommended that a thorough analysis of mapping JSON data to RDF using JSON-LD be conducted in a future activity, specifically taking into account the JSON Schema conversion rules developed in UGAS-2020. That activity should investigate how JSON-LD context documents can automatically be derived from an application schema, given a set of ontology and JSON Schema encoding rules that apply to the application schema. The analysis should be accompanied by a prototypical implementation.
The following paragraphs summarize the results of the investigations on JSON-LD that were conducted in UGAS-2020.
The JSON Schema conversion of code lists describes three different ways to encode code lists and thus also code values.
-
By default, code lists are converted to a simple JSON Schema "type" definition, typically a string. Using a tagged value, it is also possible to use other JSON Schema types, for example a number (for a list of numeric codes).
-
Using rule-json-cls-codelist-uri-format, codes will be represented as JSON strings, with format "uri."
-
Finally, using rule-json-cls-codelist-link, it is also possible to convert a code list using a JSON Schema reference to a link object.
In the first two cases, a code is represented by a simple JSON value, while in the case of a link object, a code is represented by a JSON object.
The cases where a code is represented by anything other than a simple JSON string are problematic when using JSON-LD to map JSON data to RDF. The reason is that, following the ISO 19150-2 conversion rule for code lists (as documented in the [OGC Testbed-12 ShapeChange Engineering Report]), codes are represented in RDF/OWL as individuals - which are directly used as the RDF/OWL property that represents a code list valued UML property.
If the JSON representation of a code is a JSON number, then that number cannot be mapped to RDF using JSON-LD. That is a limitation of JSON-LD, which is documented in more detail in the OGC Testbed-14: Application Schemas and JSON Technologies Engineering Report, section 6.2.2.2.
If the JSON representation of a code is a link object, with one of the members of the (JSON) link object containing the code value, then the link object cannot be mapped to a simple RDF/OWL individual using JSON-LD. Instead, the mapping result would be an RDF resource that represents the link object, with a property that represents the member that contains the code value. Consider the example shown in Listing 2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"@context": {
"@version": 1.1,
"ex": "http://example.com/myontology",
"excode": "http://example.com/myontology/mycodelist",
"codeValuedProperty": {
"@id": "ex:myCodeProperty",
"@context": {
"codeList": "@type",
"codeListValue": {
"@id": "ex:code",
"@type": "@vocab"
},
"a": "excode:codeA",
"b": "excode:codeB"
}
}
},
"codeValuedProperty": {
"codeList": "http://example.com/myontology/mycodelist",
"codeListValue": "a"
}
}
A link object always has a specific structure, which in this example is related to the encoding of code values in ISO 19139. As we can see, the code value is encoded within the "codeListValue" member. Running this example in the JSON-LD playground, we get the N-Quads representation shown in Listing 3.
Note
|
N-Quads is one of several formats for encoding RDF data. |
1
2
3
_:b0 <ex:myCodeProperty> _:b1 .
_:b1 <ex:code> <excode:codeA> .
_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.com/myontology/mycodelist> .
We can see that the code value is encoded as property value of a nested resource (blank node b1), instead of being the actual value of ex:myCodeProperty, which would be expected for the RDF/OWL encoding that is based on the ISO 19150-2 conversion rule for code lists.
This mismatch can be prevented if the code value was a simple JSON string, see Listing 4, and the resulting N-Quads in Listing 5.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"@context": {
"@version": 1.1,
"ex": "http://example.com/myontology",
"excode": "http://example.com/myontology/mycodelist",
"codeValuedProperty": {
"@id": "ex:myCodeProperty",
"@type": "@vocab",
"@context": {
"a": "excode:codeA",
"b": "excode:codeB"
}
}
},
"codeValuedProperty": "a"
}
1
_:b0 <ex:myCodeProperty> <excode:codeA> .
With the code value being a uri encoded as a JSON string which is the same IRI as the individual that identifies the code in the ontological representation, the JSON data would be even easier to map to RDF using JSON-LD - see Listing 6, which results in the same RDF data as shown in Listing 5.
1
2
3
4
5
6
7
8
9
10
11
{
"@context": {
"@version": 1.1,
"ex": "http://example.com/myontology",
"codeValuedProperty": {
"@id": "ex:myCodeProperty",
"@type": "@id"
}
},
"codeValuedProperty": "http://example.com/myontology/mycodelist/codeA"
}
5.1.3. Continue work on a JSON encoding for features
The Features Core Profile and its JSON encoding build on the widely used GeoJSON standard and extends it with minimal extensions to support additional concepts that are important for the wider geospatial community and the OGC API standards, including support for solids, coordinate reference systems, and time intervals. A new Standards Working Group for a standard OGC Features and Geometries JSON has been proposed.
The design of the JSON encoding should be:
-
validated through multiple implementations writing and reading such JSON;
-
validated through additional experiments with extensions to ensure its extensibility; and
-
kept consistent with the JSON Schema encoding rule for GeoJSON that has been specified in this ER.
5.1.4. Investigate the impact of OCL language constructs unsupported by SHACL for the NAS
Three approaches for translating OCL constraints using SHACL have been investigated in UGAS-2020. None of them supports a full translation of all OCL language constructs that were investigated. It would be useful to analyze the frequency of use of non-supported OCL language constructs and/or the significance/impact of avoiding their use in the NAS. The results would help make a decision of which of the three approaches would be best suited for implementation, in support of encoding the knowledge contained in NAS OCL constraints in SHACL.
5.1.5. Revise the OWL conversion rule for basic types
rule-owl-cls-encode-basictypes, an OWL conversion rule for basic types developed in OGC Testbed-12, converts basic types - i.e., classes that inherit (directly or indirectly) from a simple type (e.g., CharacterString) - to OWL classes. That means that a basic type value always needs to be encoded as an instance. However, whenever the supertype of a basic type is mapped to an RDFS/OWL datatype, one would expect that a value of this basic type is encoded as a literal (with the according datatype).
The conversion rule should be revised, and the implementation in the ShapeChange ontology target be updated accordingly.
A basic type with a supertype that maps to an RDFS/OWL datatype should be defined as a custom datatype, which restricts the XSD datatype of the RDFS/OWL datatype using an OWL DatatypeRestriction. That restriction defines the restricting facets (defined for the basic type, typically using tagged values), such as xsd:minInclusive.
A custom datatype can be used in the range declaration of an OWL data property. However, a custom datatype cannot be used within an OWL DatatypeRestriction because "datatypes defined by datatype definition axioms support no facets" (source: https://www.w3.org/TR/owl-syntax/#Datatype_Definitions). That means that a basic type A, which is defined in UML as a subtype of another basic type B, cannot be expressed using B as datatype in the OWL DatatypeRestriction. Instead, basic type A needs to be defined as a datatype with an OWL DatatypeRestriction that combines all restricting facets from its direct and indirect supertypes (here: B) and the restrictions declared for basic type A itself.
Example:
-
A type PositiveReal, which inherits from Real and restrict the value space to non-negative double values (so including zero), would be represented as:
DatatypeDefinition(<PositiveReal> DatatypeRestriction(xsd:double xsd:minInclusive "0"^^xsd:double))
-
A type Real0to400, which inherits from PositiveReal and restricts the value space to [0,400], would be represented as:
DatatypeDefinition(<Real0to400> DatatypeRestriction(xsd:double xsd:minInclusive "0"^^xsd:double xsd:maxInclusive "400"^^xsd:double))
Note
|
ShapeChange map entries for RDFS/OWL datatypes will need to provide the XSD datatype (e.g., via a map entry parameter) that is used by the RDFS/OWL datatype, plus information about any restricting facets, so that the custom datatype definition can be created. Alternatively, ShapeChange could try to parse that information from the vocabulary definition of the RDFS/OWL datatype. This requires further investigation and actual testing. |
Note
|
Subtypes of type Measure, defined in an application schema with the intent to define some restrictions (e.g., restricting the value range from 0 to 360), would only qualify for this kind of encoding in OWL if Measure was mapped to an RDFS/OWL datatype. |
6. UML to JSON Schema Encoding Rule
6.1. Overview
ISO / TC 211 defines Standards in the field of digital geographic information. A couple of these Standards, especially ISO 19109, are used by the geospatial community to define so called application schemas. An application schema is a conceptual schema for data required by one or more applications. It is typically defined using the Unified Modeling Language (UML).
OGC 07-036r1 defines rules for encoding an application schema in XML. The result is an XML Schema, which defines the structure for encoding application data in XML. Applications would use this XML as a format for interoperable information exchange.
XML has been and still is a widely used format for encoding data on the web. However, web applications also use other formats. JSON is another prominent format for encoding and exchanging data on the web. The ISO / TC 211 standards do not define rules for encoding an application schema in JSON. The main reason for this gap likely is that in the past, XML was a more prominent format than JSON for (geospatial) web service interactions. Another reason could be that a schema language for JSON has not fully been standardized yet. JSON Schema is such a language. The JSON Schema specification - a draft IETF standard - has improved considerably over the past couple of years. It is a serious candidate for the definition of rules for encoding application schema data in JSON.
Note
|
The current version of JSON Schema, in early 2020, is draft 2019-09. It consists of three documents, JSON Schema core ([1]), a schema for validation ([2]), and a hyper schema ([3]). For the analysis in UGAS-2020, the first two documents were of primary interest. Note also that the website http://www.json-schema.org provides a list of the current and older drafts of the specification, as well as the latest unreleased version. The site also provides an overview of existing JSON Schema implementations. |
In UGAS-2020, JSON Schema draft 2019-09 was analyzed and a set of rules as well as recommendations for converting an application schema in UML to JSON Schema has been developed. These rules and recommendations are documented in the following sections.
6.2. Schema Conversion Rules
The following subsections describe a number of conversion rules, which define how the content of an application schema, represented using UML as the conceptual schema language, is converted to JSON Schema.
Note
|
An encoding rule consists of a set of conversion rules – as required by a community. The Encoding Rules section describes two such rules - one for a GeoJSON compliant encoding, and one for a plain JSON encoding. |
6.2.1. Documentation
With rule-json-all-documentation, descriptive information of application schema elements (packages, classes, properties, and associations) can be encoded via JSON Schema annotations.
Note
|
Annotations represent one category of JSON Schema keywords (for further details, see JSON Schema core, section 7). Annotations attach information that applications may use as they see fit. The other categories are assertions, which validate that a JSON instance satsifies constraints, and applicators, which apply subschemas to parts of the instance and combine their results. |
Warning
|
In UGAS-2020, only the design for converting the documentation of application schema elements has been developed. rule-json-all-documentation has not been implemented in UGAS-2020, for two reasons.
|
Descriptive information of a model element in ShapeChange, i.e., properties (attributes and association roles), classes, and packages, includes the pieces of information, called descriptors, that are documented in Table 1.
Note
|
A model element can have all, a subset, or none of these descriptors. |
Descriptor Name (and ID) |
Explanation | ||
---|---|---|---|
Name |
The name of the model element (as named in the source UML, i.e., using upper and lower camel case). |
||
Alias |
An alternative, human-readable name for the model element. |
||
Definition |
The normative specification of the model element. |
||
Description |
Additional information about the model element. |
||
Documentation |
The overall documentation of the model element. May be structured, containing other descriptors (such as definition and description). |
||
Example(s) |
Example(s) illustrating the model element. |
||
Global identifier |
The globally unique identifier of the model element; that is, unique across models. |
||
Legal basis |
The legal basis for the model element. |
||
Data capture statement(s) |
Statement(s) describing how to capture instances of this model element from the real world. |
||
Primary code |
The primary code for this model element.
|
Note
|
The descriptor ID is used in ShapeChange configuration elements that define JSON Schema annotations. |
Typically, a community has a preferred way to model and encode this information. For example, one community may want to encode the description of a model element via the "description" annotation (which is one of a set of basic meta-data annotations defined in JSON Schema validation, section 9), while another may prefer to encode the values of multiple descriptors of a model element within a single "description" annotation.
ShapeChange can support this type of diversity through JSON Schema annotation elements, which can be defined in the ShapeChange configuration. An annotation element specifies how the content of a specific JSON Schema annotation (that shall be generated while converting a model element) shall be constructed. The annotation element takes into account that a UML model element may not have an actual value for a descriptor, and that some descriptors can have multiple values, e.g., the descriptor example.
In addition to the well-known descriptors (see previous table), additional descriptive information can be incorporated through UML tagged values from the application schema. For example, the "name" tagged value on classes in the NAS could be used to create a JSON Schema "title" annotation.
Different types of annotation elements are available for configuring a ShapeChange JSON Schema target.
-
JsonSchemaNumberAnnotation - For annotations with a(n array of) JSON number(s) as value.
-
JsonSchemaBooleanAnnotation - For annotations with a(n array of) JSON boolean(s) as value.
-
JsonSchemaStringAnnotation - For annotations with a(n array of) JSON string(s) as value.
-
JsonSchemaTemplateAnnotation - For annotations with a(n array of) JSON string(s) as value, defined via a template that can include multiple descriptors and tagged values.
Note
|
The JSON Schema annotation "examples," defined by JSON Schema validation, section 9.5, is an example for an annotation that has a JSON array as value, with the type of array items being unrestricted. In other words, the array can contain mixed value types. The "examples" annotation can thus have an array of strings (e.g., ["abc","xyz"]), numbers (e.g., [4,2]), booleans (e.g., [true, true]), and a mix thereof (e.g., ["abc", 2, true]) as value. |
Note
|
ShapeChange JSON Schema annotation elements are not designed to support the creation of annotations with complex JSON arrays or objects as value. Only simple values, or an array thereof, can be created. So far, no use cases have been identified that require a more complex annotation value. In the future, if such use cases were identified, ShapeChange could be extended to support them. |
The following two tables document the structure of ShapeChange JSON Schema annotation elements. Listing 7 provides examples.
Configuration Information Item | Datatype & Structure | Required / Optional | Default Value | Description |
---|---|---|---|---|
annotation |
string |
Required |
not applicable |
Name of the JSON Schema annotation keyword that shall be added to the JSON Schema element which represents the UML model element. |
descriptorOr TaggedValue |
string |
Required |
not applicable |
Either a descriptor-ID, identifying one of the well-known descriptors, or a string identifying a tagged value. In order to identify a tagged value, add prefix "TV:" to the name of the tagged value. If a tagged value is known to contain a list of values, combined in a string using a specific separator, and these values shall be used as individual values, rather than using the whole string as value, use the prefix "TV(separator):," followed by the tag name. ShapeChange will then split the tagged value around matches of the given separator (which is treated as a literal). Note that the type of the ShapeChange JSON Schema annotation element defines how ShapeChange will encode the values of the descriptor / tagged value.
|
noValueBehavior |
enum: ignore or populateOnce |
Optional |
ignore |
Determines the behavior in case that no value is available for the descriptor or tagged value.
|
noValueValue |
string |
Optional |
the empty string |
If the descriptor or tagged value has no value, then this information item provides the value to use instead (e.g., 0, or true). |
arrayValue |
boolean |
Optional |
false |
If true, then the annotation value will always be encoded as an array, even if only a single value is present. Otherwise, the default behavior is to only encode multiple values within a JSON array. |
Information Item | Datatype & Structure | Required / Optional | Default Value | Description |
---|---|---|---|---|
annotation |
as defined in the previous table |
|||
valueTemplate |
string |
Required |
not applicable |
Textual template where an occurrence of the field "[[descriptor-ID]]" is replaced with the value(s) of that descriptor. The IDs of supported descriptors are listed in the table above. An occurrence of the field "[[TV:name]]" is replaced with the value(s) of the UML tagged value with the given name from the input schema. The content of a tagged value can also be split into multiple parts. In that case, use field "[[TV(separator):name]]." The tagged value will be split around matches of the given separator (which is treated as a literal). |
noValueBehavior |
enum: ignore or populateOnce |
Optional |
ignore |
Determines the behavior in case that no value is available for any of the fields (tagged values and descriptors) contained in the template.
|
noValueValue |
string |
Optional |
the empty string |
If a descriptor used in a template has no value, then this information item provides the value to use instead (e.g., "N/A" or "FIXME"). |
arrayValue |
as defined in the previous table |
|||
multiValueBehavior |
enum: either connectInSingleAnnotationValue or createMultipleAnnotationValues |
Optional |
connectInSingleAnnotationValue |
Specifies how a case where one or more of the descriptors and tagged values contained in the template have multiple values, shall be encoded.
|
multiValue ConnectorToken |
string |
Optional |
a single space character |
If a descriptor or tagged value used in the valueTemplate has multiple values, and the multiValueBehavior is set to connectInSingleAnnotationValue, then the values are concatenated to a single string value using this token as connector between two values. |
Note
|
Conversion rules exist to populate "default" and "readOnly". For further details, see sections Fixed / readOnly and Initial Value. |
1
2
3
4
5
6
7
8
9
<annotations>
<JsonSchemaBooleanAnnotation annotation="deprecated" descriptorOrTaggedValue="TV:deprecated"/>
<JsonSchemaNumberAnnotation annotation="code" descriptorOrTaggedValue="TV:codeNumber"/>
<JsonSchemaStringAnnotation annotation="title" descriptorOrTaggedValue="alias" noValueBehavior="populateOnce" noValueValue="NA"/>
<JsonSchemaStringAnnotation annotation="label" descriptorOrTaggedValue="TV(|):aliasList"/>
<JsonSchemaStringAnnotation annotation="examples" descriptorOrTaggedValue="example" arrayValue="true"/>
<JsonSchemaTemplateAnnotation annotation="description" valueTemplate="Definition: [[TV:definition]] Description: [[TV:description]]" noValueValue="[None Specified]"/>
<JsonSchemaTemplateAnnotation annotation="isDefinedBy" valueTemplate="http://nsgreg.nga.mil/as/view?i=[[TV:itemIdentifier]]"/>
</annotations>
6.2.2. Schema Packages
Schema packages have the stereotype <<applicationSchema>>, <<schema>>, or an alias (e.g., using a specific language, like <<anwendungsschema>>). An <<applicationSchema>> package represents an application schema according to ISO 19109. The stereotype <<schema>> has been introduced for packages that should be treated like application schemas, but do not contain feature types.
6.2.2.1. Definitions Schema
A UML application schema and its classes are converted into one or more so-called definitions schemas. A definitions schema is a JSON Schema that has the "$defs" keyword.
Note
|
In the JSON Schema specification draft, version 07, the keyword of the definitions section was "definitions". In JSON Schema specification draft, version 2019-09, the keyword was changed to "$defs." |
The "$defs" keyword has a JSON object as value, where each member represents the JSON Schema definition of a class from the application schema.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"$schema": "http://json-schema.org/draft/2019-09/schema",
"$defs": {
"Class1": {
"type": "object",
"properties": {
"prop1": {"type": "string"}
},
"required": ["prop1"]
},
"Class2": {
"type": "object",
"properties": {
"prop2": {"type": "number"}
},
"required": ["prop2"]
}
}
}
Note
|
The current definitions schema examples in this document mostly use "definitions" instead of "$defs." The reason is that most JSON Schema validators support JSON Schema draft-07, but at the time when the examples were developed, these validators did not fully support JSON Schema 2019-09. |
By default, a UML application schema is encoded as a single definitions schema. By setting tagged value jsonDocument on subpackages of the schema package, the classes within these packages (as well as subpackages for which the tagged value is not set) will be encoded in additional definitions schemas.
Note
|
Tagged value jsonDocument can also be set on the schema package itself, to define the file name of the definitions schema that will be produced for the schema package. If tagged value jsonDocument is not defined for the schema package, or does not have a value, then ShapeChange will use the package name as fallback, replacing all spaces and forward slashes with underscores, and appending '.json'. For example, if a schema package was named 'Ba / nanas' then the file name would be 'Ba___nanas.json'. |
Note
|
If the conversion process does not add any actual definitions to a definitions schema, then that schema will not be written by ShapeChange. Reasons for no definition being added to a definitions schema are:
|
Figure 1 provides an example of a UML application schema, where the tagged value is set both on the schema package itself and on one of its leaf packages. Figure 2 illustrates the structure of the resulting definitions schemas.
References from types of the application schema to other types (within the same or within an external schema) are converted as references to the according definitions schemas, using the JSON Schema keyword "$ref" - see Figure 3.
A link to a particular definition within a definitions schema requires the use of a JSON Pointer or an anchor in the fragment identifier of the link URL.
JSON Pointer, chapter 6, explicitly states that the media type in which a JSON value is provided needs to support this kind of fragment identifier, and that this is not the case for the media type application/json. If a JSON Schema was published with this media type, then it is possible that the application ignores a fragment identifier (because the media type does not support fragment identifiers).
Definitions schemas therefore should not be published under media type application/json. Instead, a JSON Schema should be published with media type application/schema+json - which is defined by the JSON Schema specification. The media type application/schema+json supports JSON Pointers and plain names as fragment identifiers. For further details, see JSON Schema core, chapter 5.
Note
|
The JSON Schema that shall be used to validate a JSON document cannot be identified within that document itself. In other words, JSON Schema does not define a concept like an xsi:schemaLocation, which is typically used in an XML document to reference the applicable XML Schema(s). Instead, JSON Schema uses link headers and media type parameters to tie a JSON Schema to a JSON document (for further details, see JSON Schema core, sections 11.1 and 11.2). The relationship between a JSON document and the JSON Schema for validation can also be defined explicitly by an application. |
6.2.2.2. JSON Schema Version
According to JSON Schema core, section 8.1.1, the root schema of a JSON Schema document should contain a "$schema" keyword. The value of this keyword identifies the JSON Schema meta-schema against which the schema is valid. Typically, that is a meta-schema defined by a specific version of the JSON Schema specification.
The "$schema" keyword is therefore added to the definitions schema. Its value is defined via the ShapeChange JSON Schema target configuration parameter jsonSchemaVersion. The values supported for the parameter are:
-
"2019-09" (the default value of the parameter) - corresponding to the schema URI "https://json-schema.org/draft/2019-09/schema"
-
"draft-07" - corresponding to the schema URI "http://json-schema.org/draft-07/schema#"
-
"OpenApi30" - with no schema URI; introduced to support the OpenAPI 3.0 Schema object, which will become obsolete once OpenAPI 3.1 has been adopted (for further details, see JSON Schema variants)
Note
|
The ShapeChange JSON Schema target supports both JSON Schema 2019-09, and the older draft 07, because implementation support for the latter was more prevalent at the time when the JSON Schema work was conducted in UGAS-2020. |
Note
|
The "$schema" of the definitions schema examples in this document is mostly set to "http://json-schema.org/draft-07/schema#." The reason is that most JSON Schema validators support JSON Schema draft-07, but at the time when this chapter was written they did not fully support JSON Schema 2019-09. |
6.2.2.3. Schema Identifier
According to JSON Schema core, section 8.2.2.1, the root schema of a JSON Schema document should contain an "$id" keyword with an absolute URI. The "$id" identifies the schema resource with its canonical URI.
Note
|
The URI is an identifier and not necessarily a resolvable URL. If the "$id" is a URL, there is no expectation that the JSON Schema can be downloaded at that URL. However, it is recommended that the URL is stable, persistent, and globally unique. |
The definitions schemas derived from the application schema package thus each receive a unique "$id." The value of this id uses the following URI template.
{jsonBaseUri}/{jsonDirectory}/{jsonDocument}
Where:
-
{jsonBaseUri} is either specified via tagged value jsonBaseUri on the application schema package, or defined via the ShapeChange JSON Schema target configuration parameter jsonBaseUri (which has default value "http://example.org/FIXME"). If both are defined, the tagged value takes precedence over the configuration parameter.
-
{jsonDirectory} is the value of the tagged value of the same name on the application schema package. If that tagged value is undefined, the value of the xmlns tagged value is used. If that tagged value is also not defined, then the string default is used.
-
{jsonDocument} is the file name of the definitions schema, which is either defined in the UML model using tagged value of the same name on a package, or automatically derived from the application schema name.
Example: With jsonBaseUri = https://example.org
, jsonDirectory = json/schemas/schemaX/1.0
, and jsonDocument = testschema.json
, ShapeChange will produce:
"$id": "https://example.org/json/schemas/schemaX/1.0/testschema.json"
Note
|
The "$id" of the definitions schema is not included in other examples within this chapter, because declaring an absolute, non-existent URL in these examples often prevents JSON Pointers from these examples from working when testing the examples, for instance on https://www.jsonschemavalidator.net/ (which is a useful tool for testing JSON Schema). |
6.2.3. Types
6.2.3.1. Mappings
Application schemas typically use types from other schemas, for example the types defined by ISO 19103 and ISO 19107. External types can be used as value types of properties, and as supertypes for types defined in the application schema that is being converted.
Whenever an external type is used, its JSON Schema definition is needed. Either an external type is implemented as one of the simple JSON value types (e.g., string - maybe with a certain format), or it is defined by a particular JSON Schema. In case of a JSON Schema, the URL of that schema needs to be known during the conversion process. If the schema is a definitions schema, then the URL needs to be augmented with a fragment identifier that includes a JSON Pointer or an anchor reference within the schema.
Information about the JSON Schema implementation of external types must explicitly be provided to the ShapeChange JSON Schema target via so called map entries. These map entries are part of the target configuration. A map entry of the JSON Schema target must:
-
identify the schema type that is being mapped, by name
-
define the JSON Schema implementation of that type:
-
either as one of the few simple JSON value types (string, number, integer, boolean), potentially with additional keywords conveyed via map entry parameter:
-
for any simple JSON value type: keyword format
-
for JSON value type string: keywords enum, const, pattern, maxLength, minLength
-
NOTE: Complex regular expressions intended to be used as pattern may need to be base64 encoded, in order to avoid problems with syntax rules of the map entry parameter. For base64 encoded regular expressions, use the patternBase64 characteristic of the ShapeChange map entry parameter keywords.
-
-
for JSON value types integer and number: keywords enum, const, multipleOf, maximum, minimum, exclusiveMaximum, exclusiveMinimum
-
-
or as a URL that references the JSON Schema definition of the external type
-
-
declare the path to the JSON member that is used to encode the name of the type that the JSON object represents, (e.g., "type", "entityType", or "properties/observationType") - if such a member exists in the target type
-
This information is useful to support specialization (for further details, see Class Specialization and Property Ranges) and encoding value type options.
-
The Features Core Profile of Key Community Conceptual Schemas chapter documents a core profile of ISO schemas that are used in the NSG, as well as the JSON Schema definitions for the types contained in that profile. In UGAS-2020, type mappings have been created for this profile, in order to create a NAS JSON Schema. The mappings can also be used for the conversion of other application schemas.
6.2.3.2. Class Name
The following use cases have been identified where converting the name of a type is useful.
-
Defining location independent identifiers within the definitions schema, to create simple references to schema definitions.
-
Supporting type identification, thereby enabling at least some level of type inheritance checks and semantic mapping.
6.2.3.2.1. Location Independent Schema Identifiers
With rule-json-cls-name-as-anchor, the name of a class is encoded as an "$anchor," which is added at the start of the schema definition of the class (within the definitions schema). Schema definitions that have an "$anchor" can be referenced using the plain text value of the anchor as fragment identifier, instead of using a more complex JSON Pointer.
Note
|
The "$anchor" keyword was added in JSON Schema draft 2019-09. It replaces the somewhat ambiguous use of the "$id" keyword in JSON Schema draft 07 to define plain name fragment identifiers for subschemas. For further details, see section 8.2.3 of both JSON Schema draft 2019-09 and JSON Schema draft 07. |
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"$schema": "http://json-schema.org/draft/2019-09/schema",
"$defs": {
"TypeA": {
"$anchor": "TypeA",
"...": "..."
},
"TypeB": {
"$anchor": "TypeB",
"...": "..."
}
}
}
If the ShapeChange target parameter jsonSchemaVersion (see JSON Schema Version) is set to "draft-07," then rule-json-cls-name-as-anchor results in the creation of the "$id" keyword, instead of the "$anchor" keyword.
Note
|
JSON Schema draft 07 requires the value of "$id" to start with "#", thus when producing a JSON Schema compliant to JSON Schema draft 07, the combination of "#" and the class name is used as value of the "$id" key. |
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"TypeA": {
"$id": "#TypeA",
"...": "..."
},
"TypeB": {
"$id": "#TypeB",
"...": "..."
}
}
}
6.2.3.2.2. Type Identification
rule-json-cls-name-as-entityType adds another JSON member to the JSON object which represents the class that is being converted.
The name of the JSON member can be configured using the ShapeChange JSON Schema target parameter entityTypeName. The default value of the parameter is "entityType". The JSON member is required and string-valued. It should be used to encode the name of the type that is represented by the JSON object.
Note
|
By default, the property value is not restricted using "const", because doing so would prevent JSON Schema constraints that support inheritance-related checks. However, if the application schema did not use inheritance, then such restrictions could be defined. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Type": {
"properties": {
"entityType": {
"type": "string"
},
"property": {
"type": "string"
}
},
"required": [
"entityType", "property"
]
}
},
"$ref": "#/definitions/Type"
}
The following JSON instance is valid against the schema:
1
2
3
4
{
"entityType": "Type",
"property": "x"
}
Encoding the type name in JSON objects is useful.
-
Encoding the type of a JSON object together with its other properties supports a more complete validation of property values, where the property type is a supertype. For further details, see Value Type.
-
As described in chapter 6 of the OGC Testbed-14: Application Schemas and JSON Technologies Engineering Report, having a key within a JSON object with a string value that identifies the type of the object allows that object to be mapped to RDF. More specifically, the string value can be mapped to an IRI that identifies the type of an RDFS resource.
There are also some cases in which rule-json-cls-name-as-entityType is ignored or conditional.
-
To prevent the addition of unnecessary JSON members (here: because the JSON member would already be inherited), the rule is ignored for a type T if T is a subtype and rule-json-cls-name-as-entityType already applies to one of its supertypes.
-
By default, the rule does not apply to unions, enumerations, and code lists.
However, if rule-json-cls-name-as-entityType-union is enabled together with rule-json-cls-name-as-entityType, then the latter also applies to unions. The considerations that led to the addition of the former conversion rule are: Unions can be converted to JSON objects (see Union, more specifically: Property Choice). The ontology target of ShapeChange encodes a union as a class, with cardinality restrictions to ensure that only one option (defined by the union) is used. For further details, also see the OGC Testbed-12 ShapeChange Engineering Report. This is an argument for applying rule-json-cls-name-as-entityType to unions, because it would support a JSON-LD based mapping to the union class in RDF/OWL.
6.2.3.3. Abstractness
JSON Schema does not directly support abstractness. An abstract class is therefore encoded like a non-abstract class.
Note
|
Encoding a JSON object that represents an abstract type, with the "entityType" having the abstract type name as value, would be useful with regards to linked data applications, and conversion of JSON data to RDF using JSON-LD. Abstractness is also not supported in RDF/OWL, so RDF resources can define the RDFS/OWL class or datatype, which represent an abstract type from the conceptual model, as their type. That makes sense for cases in which the exact type of a resource or "thing" is not known yet, but a more general type is. |
6.2.3.4. Inheritance
JSON Schema does not support the concept of inheritance itself. A workaround for this issue would be to transform the conceptual model and flatten all inheritance hierarchies. For further details, see Flattening Inheritance.
The following sections document the conversion of an inheritance relationship, covering the topics of Class Generalization and Property Inheritance and Class Specialization and Property Ranges. A special case of generalization, for classes with specific stereotypes, is discussed in section Virtual Generalization.
6.2.3.4.1. Class Generalization and Property Inheritance
The generalization relationship of a subtype to its supertype is converted by combining the structural constraints of the subtype and its supertype using the JSON Schema keyword "allOf."
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"TypeA": {
"properties": {
"propertyA": {
"type": "number"
}
},
"required": [
"propertyA"
]
},
"TypeB": {
"allOf": [
{
"$ref": "#/definitions/TypeA"
},
{
"type": "object",
"properties": {
"propertyB": {
"type": "string"
}
},
"required": [
"propertyB"
]
}
]
}
},
"$ref": "#/definitions/TypeB"
}
This JSON object is valid against the schema from Listing 12:
1
2
3
4
{
"propertyA": 2,
"propertyB": "x"
}
This JSON object is invalid (because "propertyA" is missing) against the schema from Listing 12:
1
2
3
{
"propertyB": "x"
}
Note
|
This also works for an encoding where the properties of a class are nested within a key-value pair (like "properties" for a GeoJSON encoding). |
Note
|
The case where a property from a supertype is redefined by a property from the subtype is supported. Redefinition in UML requires that the value type of the subtype property is "kind of" the type of the redefined property of the supertype. Therefore, the property value, when encoded in JSON, would satisfy the JSON Schema constraints defined by both the subtype property and the redefined supertype property. |
This approach to converting a generalization relationship has the following restrictions.
-
The JSON Schema keyword "additionalProperties" must not be set to false in the definitions of both the super- and the subtype.
-
The approach only works for generalization relationships of feature, object, and data types. For unions, enumerations, and code lists generalization relationships are not supported.
-
It only converts the generalization relationship from subtype to supertype. It does not support the other direction of an inheritance relationship, i.e., specialization. Given a JSON object that encodes a subtype, and the JSON Schema of the supertype, then only the constraints of the supertype are checked, but not all the constraints that apply to the subtype. That is an issue when encoding a UML property whose value type is or could be a supertype (via a subtype that is added by an external, so far unknown schema). Conceptually, the actual value of that property can be a supertype object, but it could just as well be an object whose type is a subtype of that supertype. This issue can only be solved to a certain degree with JSON Schema, as explained in the Class Specialization and Property Ranges section.
Multiple inheritance is supported by adding all supertypes as elements of "allOf."
6.2.3.4.2. Virtual Generalization
It is often useful to encode all classes with a certain stereotype with a common base type. The generalization relationship to such a base type is often implied with the stereotype, for a given encoding. In GML, for example, the common base type for classes with stereotype <<featureType>> is gml:AbstractFeature. Rather than explicitly modeling such a base type (e.g., AnyFeature defined by ISO 19109), as well as explicitly modeling generalization relationships to the base type, the encoding rule typically takes care of adding that relationship to relevant schema types.
This kind of virtual generalization is supported via rule-json-cls-virtualGeneralization. The rule adds generalization relationships to specific kinds of classes - if a) according ShapeChange JSON Schema target parameters have been set, and b) the class does not already have that generalization relationship via one of its supertypes:
-
feature type - configuration parameter baseJsonSchemaDefinitionForFeatureTypes
-
object type - configuration parameter baseJsonSchemaDefinitionForObjectTypes
-
data type - configuration parameter baseJsonSchemaDefinitionForDataTypes
The parameter value shall be a URI to reference the JSON Schema that defines the common base type. For example, in order for all feature types to use the GeoJSON Feature definition as common base, set baseJsonSchemaDefinitionForFeatureTypes = https://geojson.org/schema/Feature.json
.
Note
|
Being able to choose any URI as parameter value can be useful for offline and private-network situations. |
Note
|
The parameters do not have a default value. If a parameter is not set or does not have a value, then rule-json-cls-virtualGeneralization will not have an effect for the kind of class (feature, object, or data type) for which the parameter applies. |
The virtual generalization relationship is implemented by converting the class to a JSON Schema that consists of an "allOf" with two subschemas: the first being a "$ref" with the URI defined by the target parameter, the second being the schema produced by applying the other conversion rules to the class.
The only exception is rule-json-cls-name-as-anchor, because the "$anchor" created by that rule is not encoded in the second subschema, but in the schema that contains the "allOf".
6.2.3.4.3. Class Specialization and Property Ranges
By default, validation of a property value encoded in JSON, with the value having a complex type (i.e., being a JSON object or an array of JSON objects), only encompasses checking the JSON Schema constraints defined for that type. If the property value actually is a subtype of that type, then the constraints defined for that subtype would not be checked. Ideally, the constraints of known and unknown subtypes would automatically be checked, but JSON Schema does not support this.
Note
|
If JSON data was transformed to RDF using JSON-LD, then class specialization and property ranges could fully be checked by validating the RDF data using SHACL. For further details, see the SHACL Conversion Rules section of this document. |
To a limited extent specialization relationships could be represented in JSON Schema, but only for subtypes in the same schema/model and using complex, verbose constructs from JSON Schema. This would make the schemas hard to read (by humans) and to parse (by application schema parsers in clients). The value of such a capability is therefore questionable and currently not supported.
Note
|
To capture the discussion, a potential conversion rule is documented below, but has not been implemented in the pilot. The conversion rule would support known subtypes. "Known" are the subtypes defined in the UML model that contains the application schema from which the JSON Schema is derived. There would be a limitation that subtypes from different schemas with identical class names, but conflicting definitions (e.g., A pre-condition of the conversion rule would be that the subtype name must be included in the encoding of the JSON object. The conversion rule therefore would require rule-cls-name-as-entityType (see section Type Identification) to be part of the encoding rule with the default name "entityType" - or some alternative mechanism to identify the JSON member that encodes the type. The definitions schema includes a definition for each type that is being converted. Under the additional conversion rule for specialization, a second definition would be generated for each supertype of the application schema (that is a feature, object, or data type). The name of that definition would be constructed as: The JSON Schema of the new definition would be constructed as follows.
The resulting JSON Schema looks for an "entityType" match. If one is found, the JSON object is validated against the JSON Schema definition of that type. If no match is found, then the JSON Schema of the supertype is used as a fallback for validation. The JSON object would then at least have to fulfill the constraints defined by the schema of the supertype. However, any additional content of the JSON object would not be validated. Figure 5. Example of a value type being a supertype
Listing 13. JSON Schema example of a value type definition for a supertype
The following two JSON objects are valid against the schema from Listing 13:
The next JSON object is also valid against the schema from Listing 13, because the value of "propertyC" matches the schema of supertype TypeA, even though the entity type is unknown:
The following two JSON objects are invalid against the schema from Listing 13 (in both cases because the type of "propertyA" is string instead of number):
Note that if the last else-case simply was 'false', then that would prevent any unknown subtype from being encoded - at least with the value type definition created and used within the definitions schema that is being produced. For a non-abstract supertype, the if-then-else construct would then have to contain an additional |
6.2.3.5. Feature and Object Type
In the conceptual model, feature and object types represent objects that have identity. That differentiates these types from, for example, data types. Other than that, feature and object types are encoded as JSON objects, just like a data type.
A feature or object type - in the following summarily called types with identity - is converted to a JSON Schema definition which is added to the definitions schema, using the type name as definition key. Note that ISO 19109 requires class names to be unique within the scope of an application schema.
The conversion of the class properties is defined in the Properties section. General type conversion rules, such as those documented in the Class Name section, may apply. Additional conversion rules and behavior for types with identity are described in the following sections.
6.2.3.5.1. Identifier
The conceptual model of a type with identity often does not contain a property whose value is used by applications to identify objects of that type. Instead, the according information is added or defined in platform specific encodings. For example, a GML application schema offers the gml:id attribute as well as the gml:identifier element to encode identifying information.
In a web publishing context, the URI at which a JSON object is published can be used as its identifier. Therefore, the default behavior of the ShapeChange JSON Schema target is to not add an identifier property. However, in many applications it is useful to have a member within a JSON object that provides the identifier of that object. Existing specifications often include such a capability, e.g., the "id" member in GeoJSON or "@id" in JSON-LD.
With rule-json-cls-identifierForTypeWithIdentity, an identifier JSON member will be added to the JSON object that represents the type with identity. The key, and value type of that member can be configured using ShapeChange JSON Schema target parameters:
-
objectIdentifierName: "id" (the default) or any other suitable string that does not conflict with other member names);
-
objectIdentifierType: "string" (the default), "number", or "string, number";
-
objectIdentifierRequired: "false" (the default) or "true" is used to define if the property is required or optional.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"TypeA": {
"properties": {
"entityType": {
"type": "string"
},
"id": {
"type": "string"
},
"propertyA": {
"type": "number"
}
},
"required": [
"entityType",
"id",
"propertyA"
]
}
},
"$ref": "#/definitions/TypeA"
}
The following JSON object is valid against the schema from Listing 14:
1
2
3
4
5
{
"entityType": "TypeA",
"id": "42445fdasd7asd6f7",
"propertyA": 3
}
rule-json-cls-identifierForTypeWithIdentity is ignored if one of the following conversion rules is part of the encoding rule as well:
-
rule-json-cls-identifierStereotype - This conversion rule assumes that all types with identity have an attribute with stereotype <<identifier>> (directly, or inherited from a supertype). That attribute is used to encode the identifier.
NoteIf the maximum multiplicity of an <<identifier>> attribute is greater than 1, ShapeChange will log an error. -
rule-json-cls-ignoreIdentifier - With this rule, the identifier of a type with identity will be encoded using an identifier member that is provided by a common base type (e.g., the "id" member of a GeoJSON Feature, to which a generalization relationship exists for a given feature type - see Virtual Generalization). That means that no additional identifier property is created. rule-json-cls-identifierForTypeWithIdentity is therefore overridden by rule-json-cls-ignoreIdentifier. Also, all identifier properties that are identified by rule-json-cls-identifierStereotype - if also included in the encoding rule - will simply be ignored when encoding the type with identity.
NoteThe JSON Schema for a GeoJSON Feature does not include "id" (which is defined in the GeoJSON standard, section 3.2) - not even as optional property of a "Feature". A PullRequest has been created which would fix this, see https://github.com/geojson/schema/pull/9, but it has not been merged (as of March 11, 2020).
To prevent the addition of unnecessary JSON members (here: because the JSON member would already be inherited), rule-json-cls-identifierForTypeWithIdentity is ignored for a type T if T is a subtype and rule-json-cls-identifierForTypeWithIdentity already applies to one of its supertypes.
6.2.3.5.2. Nested Properties
By default, the properties of a type are converted to first-level properties of the resulting JSON object. In GeoJSON, feature properties are encoded within the GeoJSON "properties" member. Notable exceptions from that rule are the GeoJSON members "id," "geometry," and "bbox." In order to produce a JSON Schema that converts the properties of a type with identity to be encoded within a nested "properties" member - minus any properties that are mapped to the other aforementioned GeoJSON keys - the conversion rule rule-json-cls-nestedProperties needs to be included in the encoding rule.
Note
|
Listing 26 illustrates the result of applying rule-json-cls-nestedProperties, given the feature type in Figure 15. |
6.2.3.6. Data Type
A <<dataType>> is converted to the JSON Schema definition of a JSON object. The properties of the data type are converted to the properties of that object, as described in the Properties section.
6.2.3.7. Mixin Type
ShapeChange supports the notion of mixin type (for further details, see http://shapechange.net/targets/xsd/extensions/mixin/). They are primarily used by the XML Schema target. However, if that target is contained in the ShapeChange configuration, it has implications on how UML types are loaded. In this case, it may lead to UML types being loaded as mixin types. A UML type is loaded as a mixin type if:
-
rule-xsd-cls-mixin-classes is contained in the XSD encoding rule and:
-
the tagged value gmlMixin is set to true, or
-
The type has the stereotype <<type>>, is abstract, and the tagged value gmlMixin is not set to false.
-
For the JSON Schema conversion rules, a mixin type is treated like a data type.
6.2.3.8. Union
Application schemas have two ways of using types with stereotype <<union>>.
-
According to ISO 19103:2015, a <<union>> type consists "of one and only one of several alternative datatypes (listed as member attributes). This is similar to a discriminated union in many programming languages". According to this definition, only the types of the UML attributes defined for a <<union>> are of interest.
-
In practice, unions defined in application schemas can also have another use: they define a choice between a number of options, where each option is defined by a UML attribute. In other words, the attribute itself has meaning (not just its value type). Multiple options can have the same value type. The UML-to-GML application schema encoding rules support this way of using unions (see OGC 07-036r1, section E.2.4.10).
The following sections document the conversion rules that support these two approaches of using unions.
6.2.3.8.1. Property Choice
rule-json-cls-union-propertyCount encodes a choice between the properties - i.e., the options - defined by a <<union>>.
The <<union>> is converted to the JSON Schema definition of a JSON object. Each union option is represented as an optional member of the JSON object. The choice between the options defined by the union is encoded using "maxProperties" = "minProperties" = 1. That is, the number of members that are allowed for the JSON object is restricted to exactly one.
An "additionalProperties": false
is used to prevent any undefined properties. The result of applying these rules to the union from Figure 6 is shown in Listing 15.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"UnionA": {
"type": "object",
"properties": {
"option1": {
"type": "string"
},
"option2": {
"type": "number"
}
},
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 1
}
},
"$ref": "#/definitions/UnionA"
}
Note
|
An alternative approach would be using the "oneOf" keyword, with one subschema per union property, which only defines that property, and requires it (but does not perform any other checks). This option is more verbose, harder to read and understand and, therefore, not implemented. |
This JSON object is valid against the schema from Listing 15:
1
2
3
{
"option1": "x"
}
This JSON object is invalid (because "option2" has a string value, rather than a numeric value) against the schema from Listing 15:
1
2
3
{
"option2": "x"
}
6.2.3.8.2. Type Discriminator
rule-json-cls-union-typeDiscriminator encodes a type discriminator defined by a <<union>>.
The <<union>> is converted to a JSON Schema definition that represents a choice between the value types of the union properties.
-
If the value types are only simple, without a specific format definition or other restrictions defined by JSON Schema keywords, then the JSON Schema will only contain a "type" member, with an array of the simple types.
-
Otherwise, a "oneOf" member is added to the JSON Schema definition, with:
-
one "$ref" per non-simple type,
-
one "type" for all simple types without specific keywords, and
-
one "type" per simple type with specific keywords.
-
The result of applying the rule to the union from Figure 7 is shown in Listing 15.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Union_TypeDiscriminator": {
"oneOf": [
{
"type": [
"string",
"integer"
]
},
{
"$ref": "https://geojson.org/schema/Point.json"
},
{
"type": "string",
"format": "date"
}
]
},
"Union_TypeDiscriminator_OtherTypes": {
"oneOf": [
{
"$ref": "https://geojson.org/schema/LineString.json"
},
{
"$ref": "https://geojson.org/schema/Point.json"
}
]
},
"Union_TypeDiscriminator_SimpleTypes": {
"type": [
"string",
"integer"
]
}
}
}
6.2.3.9. Enumeration
An <<enumeration>> is converted to a JSON Schema definition with a type defined by evaluating tagged value literalEncodingType. In addition, it uses the "enum" keyword to restrict the value to one of the enums from the enumeration.
The tagged value literalEncodingType identifies the conceptual type that applies to the enumeration values. If the tagged value is not set on the enumeration, or has an empty value, then the literal encoding type is set to be CharacterString. The literal encoding type is mapped to a JSON Schema type. The result should be a simple JSON Schema type (string, number, integer, or boolean). The enumeration values will be encoded accordingly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Enumeration1": {
"type": "number",
"enum": [-5, 0, 5.5]
},
"Enumeration2": {
"type": "string",
"enum": ["A","B","C"]
}
},
"anyOf": [
{"$ref": "#/definitions/Enumeration1"},
{"$ref": "#/definitions/Enumeration2"}
]
}
6.2.3.10. Code List
By default, a <<codelist>> is converted to a JSON Schema definition with a type defined by evaluating tagged value literalEncodingType.
The tagged value literalEncodingType identifies the conceptual type that applies to the code values. If the tagged value is not set on the code list, or has an empty value, then the literal encoding type is set to be CharacterString. The literal encoding type is mapped to a JSON Schema type. The result should be a simple JSON Schema type (string, number, integer, or boolean).
With rule-json-cls-codelist-uri-format, all code lists will be represented by a JSON Schema that restricts the type to "string", and states that the "format" is "uri" (as defined by JSON Schema validation, section 7.3.5).
With rule-json-cls-codelist-link, all code lists will be represented by a JSON Schema that restricts the type to a "Link" object as specified by IETF RFC 8288 and implemented in the OGC API standards. The Link object provides "href" and "title" members like the simple Xlinks in GML.
Note
|
The URL to the JSON Schema of the "Link" object (as shown in Listing 18) can be configured using the ShapeChange JSON Schema target parameter linkObjectUri. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["href","rel"],
"properties": {
"href": {
"type": "string",
"examples": ["http://data.example.com/buildings/123"]
},
"rel": {
"type": "string",
"examples": ["alternate"]
},
"type": {
"type": "string",
"examples": ["application/geo+json"]
},
"hreflang": {
"type": "string",
"examples": ["en"]
},
"title": {
"type": "string",
"examples": ["Trierer Strasse 70, 53115 Bonn"]
},
"length": {
"type": "integer"
}
}
}
In Figure 9, the encoding rule for code list "CodelistLinkObject" contains rule-json-cls-codelist-link, whereas the encoding rule for code list "CodelistUriFormat" contains rule-json-cls-codelist-uri-format, and the encoding rule for the remaining two code lists contains none of these conversion rules. The resulting JSON Schema is shown in Listing 19.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"CodelistLinkObject": {
"$ref": "http://example.org/jsonschema/link.json"
},
"CodelistNumeric": {
"type": "number"
},
"CodelistString": {
"type": "string"
},
"CodelistUriFormat": {
"type": "string",
"format": "uri"
}
}
}
Note
|
A string based code list conversion is better suited for a subsequent mapping of JSON encoded code values to RDF using JSON-LD. For further details, see the future work item Conversion of JSON data to RDF using JSON-LD. |
6.2.3.11. Basic Type
If a direct or indirect supertype of an application schema class is mapped to one of the simple JSON Schema types string, number, integer, or boolean, then under rule-json-cls-basictype that class represents a so called basic type.
A basic type does not define a JSON object. It represents a simple data value, e.g., a string. The JSON Schema definition of a basic type thus defines a simple JSON Schema type. A basic type can be restricted using a number of JSON Schema keywords. Table 4 defines which tagged values can be used to define these restrictions for a basic type, and which restrictions are available for which simple JSON Schema type.
JSON Schema keyword | tagged value to define the restriction | applicable JSON Schema type(s) |
---|---|---|
format |
jsonFormat |
string, number, integer |
maxLength |
length, maxLength, or size |
string |
pattern |
jsonPattern |
string |
minimum |
rangeMinimum |
number, integer |
maximum |
rangeMaximum |
number, integer |
Note
|
The JSON Schema keyword "format" is defined in chapter 7 of JSON Schema Validation: A Vocabulary for Structural Validation of JSON. The formats defined there (e.g., "date-time", "uri", and "json-pointer") apply to JSON values of type string. Custom formats could apply to JSON values of type number and integer. |
Note
|
JSON Schema Validation: A Vocabulary for Structural Validation of JSON defines the JSON Schema keyword "pattern". According to that specification, the value of the keyword should be a regular expression according to the ECMA 262 regular expression dialect. However, the specification does not reference a particular version or edition of ECMA 262. The regular expression dialect to be used in a JSON Schema "pattern" therefore is not exactly defined, and consequently depends on the implementation of a JSON Schema validator. In order to avoid issues with this diversity, JSON Schema: A Media Type for Describing JSON Documents defines a number of recommendations for writing regular expressions in JSON Schema. |
Note
|
The regular expression dialect used by JSON Schema is the one used by ECMA 262 (though, as said before, no specific version or edition of that standard is referenced by JSON Schema). It is unlikely that this dialect will ever be the same as the one used by XML Schema 1.1, which is for example used in XML Schema to define the pattern facet. XML Schema conversion rules supported by ShapeChange (rule-xsd-prop-constrainingFacets and rule-xsd-prop-length-size-pattern) use tagged value pattern to define the regular expression for the pattern facet in the XML Schema encoding. Due to the differences in regular expression dialects used by JSON Schema and XML Schema, rule-json-cls-basictype uses a different tagged value, namely jsonPattern, to define the regular expression for the "pattern" keyword in a JSON Schema. If the regular expression for a basic type must be different, in order to be valid in XML Schema and in JSON Schema, then both tagged value pattern and jsonPattern must be set. However, for cases in which the regular expressions used to constrain string values within the application schema are known to be valid in the regular expression dialects of both JSON Schema and XML Schema, ShapeChange offers a way to define the regular expression only once per application schema element, and still derive XML Schema and JSON Schema from the conceptual model. Tag aliases can be used in the ShapeChange configuration, to map the name of a tagged value to a different name. Tag pattern could thus be mapped to tag jsonPattern. However, tag aliases do not create copies of tagged values with different name. Tag aliasing results in renaming tags. Therefore, in order to derive both XML Schema and JSON Schema from an application schema, ShapeChange would have to be executed twice: once without mapping tag pattern, to create the XML Schema, and once with mapping tag pattern to tag jsonPattern, and then deriving JSON Schema. |
Note
|
If the "format" keyword is used to restrict the structure of a JSON string, so that it matches a certain regular expression, then it is useful to add the "pattern" keyword as well, explicitly defining that regular expression (given that the regular expression follows an ECMA 262 regular expression dialect). The reason is that the "format" is first and foremost an annotation, so can be ignored by JSON Schema validators, whereas the "pattern" keyword will be evaluated by a JSON Schema validator. JSON Schema validators may treat the "format" keyword like an assertion, but that is not guaranteed. In any case, the "format" keyword helps to convey more information about the specific type of a JSON value (e.g., "date" instead of just "string"), and thus should not be omitted if a certain, well-known (i.e., defined by a JSON Schema vocabulary) format is applicable to a JSON value. |
There are a number of cases which need to be considered when encoding a basic type.
-
The basic type directly inherits from a type that is mapped to one of the simple JSON Schema types listed above: in that case, the JSON Schema definition of the basic type will include the "type" keyword with appropriate value, and potentially also the "format" keyword if the mapping defines a specific format. In addition, restrictions defined for the basic type via tagged values are encoded using the appropriate JSON Schema keywords (as defined in Table 4).
-
Otherwise, i.e., the basic type does not directly inherit from a type that is mapped to a simple JSON Schema type:
-
If no restrictions are defined for the basic type, then the JSON Schema definition of the basic type simply contains a "$ref" to the JSON Schema definition of the direct supertype.
-
Otherwise, i.e., restricitons are defined, an "allOf" is used to refer to the JSON Schema definition of the direct supertype, and to define a JSON Schema with the restrictions that apply to the basic type.
-
Figure 10 provides a detailed example that illustrates these cases. The JSON Schema encoding is shown in Listing 20.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"MyBoolean": {
"type": "boolean"
},
"MyCharacterString": {
"type": "string"
},
"MyNumber": {
"type": "number"
},
"Number0to360": {
"allOf": [
{
"$ref": "#/definitions/NumberNonNegative"
},
{
"maximum": 360.0
}
]
},
"NumberMinus180toPlus180": {
"allOf": [
{
"$ref": "#/definitions/MyNumber"
},
{
"minimum": -180.0,
"maximum": 180.0
}
]
},
"NumberNonNegative": {
"allOf": [
{
"$ref": "#/definitions/NumberOther"
},
{
"minimum": 0.0
}
]
},
"NumberOther": {
"$ref": "#/definitions/MyNumber"
},
"String10": {
"allOf": [
{
"type": "string"
},
{
"maxLength": 10
}
]
},
"StringFormat": {
"allOf": [
{
"$ref": "#/definitions/MyCharacterString"
},
{
"format": "email"
}
]
},
"StringPattern": {
"allOf": [
{
"$ref": "#/definitions/MyCharacterString"
},
{
"pattern": "^[abc]{3}$"
}
]
}
}
}
6.2.3.12. Default Geometry
By default, any property with a geometry type is converted as any other property, with the geometry type being mapped to a JSON Schema as defined via map entries (see section Mappings).
This may not always be desired. A GeoJSON Feature, for example, has a dedicated (and required) member - "geometry" - for encoding the feature geometry. Geometry properties defined within an application schema may therefore need to be mapped to this "geometry" member. Additional conversion behavior is required to define and achieve this mapping.
Two kinds of application schemas need to be distinguished:
-
application schemas where a class has at most one geometry property, typically a property with one of the ISO 19107 geometry types as value type; and
-
application schemas where classes can have more than one geometry property.
Note
|
When counting geometry properties per class, inheritance also needs to be considered. A class that, through inheritance, has multiple geometry typed properties with different name belongs to an application schema of the second category, whereas a class that only has at most one geometry typed property - also through inheritance - belongs to the first category. |
Two conversion rules are available to support the two kinds of application schemas.
-
rule-json-cls-defaultGeometry-singleGeometryProperty - for application schemas with classes that have at most one geometry property. With this rule, the geometry property of a class represents the default geometry, and is encoded as the top-level "geometry" member. If a class has multiple - potentially inherited - geometry properties with different names, none of them is selected as default geometry (because no informed choice can be made) and ShapeChange will log an error.
-
rule-json-cls-defaultGeometry-multipleGeometryProperties - for application schemas with classes that can have multiple geometry properties. With this rule, a geometry property is identified as default geometry by setting tagged value defaultGeometry on the property to the value
true
. That property will then be encoded as a top-level "geometry" member. If multiple such properties exist (potentially inherited), none of them is selected as default geometry (because no informed choice can be made) and an error will be logged.NoteFor a class that has multiple geometry properties with different names, all such properties except the one identified as default geometry are encoded just as any other property of the class. A different behavior would be to omit these other geometry properties altogether when deriving the JSON Schema. It is unclear at this point if that would really be useful behavior. After all, the modeling expert that designed the application schema with classes that have multiple geometry properties must have had good reasons for doing so, and must also be aware that in order to perform spatial computations on the different geometry properties, special software will be required.
If a UML property is identified as default geometry, then it is implemented via the top-level "geometry" member (and not as another member of the JSON object). The "geometry" member is constrained to the JSON Schema definition to which the value type of the default geometry property is mapped.
Note
|
The schema should only use geometry types that are mapped in the configuration of the ShapeChange process. For example, in the case of a GeoJSON encoding rule, all geometry types should be mapped to GeoJSON geometry types. Otherwise the JSON Schema constraints of the GeoJSON Feature schema could not be satisfied. |
Note
|
One might think that it is beneficial to set the "geometry" member to just null if the type that is being converted does not have a default geometry. However, that must not be done in any schema conversion, because then a default geometry defined by a super- or (maybe defined in an external schema) subtype of that type could never be mapped to the "geometry" member. The only exception would be classes marked as "final," where none of the supertypes define a default geometry.
|
Note
|
If the default geometry property has a maximum multiplicity greater than 1, then ShapeChange will log a warning and assume a maximum multiplicity of exactly 1. |
Note
|
Listing 26 illustrates the result of applying rule-json-cls-defaultGeometry-singleGeometryProperty, given the feature type in Figure 15. |
Note
|
Additional geometry properties are encoded like all other UML properties (in the GeoJSON case within the GeoJSON "properties" member). |
Note
|
In some application schemas, the geometry of a feature type is not defined directly, i.e., not via a property that has an ISO 19107 type as value type. For example, consider Figure 14, where property "place" indirectly defines the geometry of a feature type, through a complex PlaceSpecification. The place is either given by a point, a curve, a surface, or by some location identifier. Such a feature model, where the geometry of a feature can be one of several geometry and non-geometry types, is not suited for the conversion rules documented in this section. |
6.2.4. Properties
A UML property of a class is converted to a member of a JSON object - unless the encoding rule defines a different behavior for the type that owns the property (e.g., for enumerations and code lists).
The default result of converting a UML property, therefore, is a key within the "properties" key of the JSON Schema definition for the type that owns the property, with the key name being the name of the UML property, and the value being a JSON Schema with constraints and annotations that define the property (value type, multiplicity, etc).
The following figure and listing provide an example: Figure 11 shows a feature type with a number of properties. Listing 21 illustrates how the UML properties are represented within the "properties" of the JSON Schema that defines that type.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"TypeX": {
"type": "object",
"properties": {
"property1": { ... },
"property2": { ... },
...
}
}
},
"$ref": "#/definitions/TypeX"
}
6.2.4.1. Value Type
If a mapping is defined for the value type of a UML property, then the JSON value type or JSON Schema defined by the mapping is used in the JSON Schema that constrains the property:
-
If the value type maps to a simple JSON value type, i.e., "string", "number", or "boolean", then a "type" key is added to the JSON Schema, with the JSON value type as value;
-
Otherwise, the mapping references a JSON Schema that defines the value type. In that case, a "$ref" key is added to the JSON Schema that constrains the property, with the reference defined by the mapping as value.
If no mapping is available, then:
-
Typically the value type is defined by one of the application schemas that are converted, and the value type itself is also converted (encoding of a type or property can be prevented with an additional rule, see Additional rules). A "$ref" key is added to the JSON Schema that constrains the property. The value of that key references the definition of the type within the definitions schema that is produced for the schema to which the type belongs. The reference uses the identifier of that schema (see Schema Identifier) as a basis, and adds a fragment identifier to identify the definition of the type. If rule-json-cls-name-as-anchor (see Location Independent Schema Identifiers) applies to the type, then the type name is used as fragment identifier. Otherwise, a JSON Pointer will be created. For example:
-
using anchor: https://example.org/schemaA/schema_definitions.json#TypeX
-
using JSON Pointer:
-
For a draft 07 JSON Schema: https://example.org/schemaA/schema_definitions.json#/definitions/TypeX
-
For a 2019-09 JSON Schema: https://example.org/schemaA/schema_definitions.json#/$defs/TypeX
-
-
-
If the value type is not defined by an application schema that is being converted, or the type itself is not converted at all, then ShapeChange will log an error and omit the type definition for the property altogether.
A specific rule has been added to support value type restrictions for UML properties, which in the NAS are defined using OCL constraints (for further details - and especially an example, see section Constraints): rule-json-cls-valueTypeOptions. This rule looks for tagged value valueTypeOptions on a class. If the tag exists and has a value, it defines which types are allowed as value type for a given UML property. Note that this UML property can be directly defined on the class but also be inherited from a supertype. The property can also originally have been an association role that belonged to an association class. The conversion rule ensures that instead of the actual value type of the property, only one of the allowed types is encoded as type definition in the JSON Schema. The conversion also takes into account that the property may have been a role of an association class. The restriction to a set of allowed types uses an if-then-else construct, which depends on the presence of a type identifying member (see section Type Identification) in property values, and thus rule-json-cls-valueTypeOptions should always be used in combination with rule-json-cls-name-as-entityType. Note that value type restrictions (defined on a subtype) of inherited UML properties will result in these properties being explicitly defined in the JSON Schema definition of the subtype. The JSON Schema types of the allowed (UML) types are determined as described before. Further details on how the tagged value valueTypeOptions is structured and how it can be derived from OCL constraints are given in section Transforming OCL Constraints Defining Value Type Restrictions.
The behavior described so far covers the case of an inline encoding of the property value. In some cases, particularly if the value type is a type with identity, it can be preferable and maybe even necessary to encode the value by reference. In other cases, both options should be offered. That is similar to what the GML Application Schema encoding rules support (for further details, see OGC 07-036r1, Annex E, section E.2.4.11).
Note
|
An example where a reference to an object is needed is when the object is the value of properties from multiple other objects that are encoded within the same JSON document. For example, a feature referenced from several other features. In such a situation, it is often desirable not to encode the object inline multiple times - especially if that object also referenced other objects. |
UML properties within an application schema typically have a tagged value inlineOrByReference, with one of three values: inlineOrByReference, byReference, or inline.
Note
|
The default value (for an empty or missing inlineOrByReference tagged value) is defined via the ShapeChange JSON Schema target parameter inlineOrByReferenceDefault. The default value of that parameter is byReference . That default value is different to GML. byReference has been chosen as default in order to reduce the degrees of freedom and to reduce the schema complexity. If association roles within an application schema had tagged value inlineOrByReference all set to inlineOrByReference, then setting target parameter inlineOrByReferenceDefault would have no effect. A by reference encoding of association roles can still be achieved with ShapeChange, using a model transformation (e.g., the identity transformation), and setting tagged values during the post-processing phase of that transformation. More specifically, one would instruct ShapeChange to set tagged value inlineOrByReference for all association roles to byReference. |
When encoding the value type of a UML property in JSON Schema, the inlineOrByReference tagged value is taken into account:
-
If the tag value is inline, then the behavior described above is applied;
-
Otherwise, if the tag value is byReference, then by default the "type" key of the property will be defined with value "string" and
"format": "uri"
.NoteThe default behavior can be overridden by setting the ShapeChange JSON Schema target parameter byReferenceJsonSchemaDefinition. The parameter value is a URI to a JSON Schema definition of a link object, for example as shown in Listing 18. In actual JSON data, such a link object would be used to encode the reference. -
Otherwise, i.e., the tag value is inlineOrByReference, the two options above are combined using the "oneOf" keyword.
NoteThe result is an XOR type of check, i.e., a value can either be given inline or by reference, but not both. This is different to GML, where in the case of inlineOrByReference and a complex value type a value can be given both inline and by reference.
This is restricted to properties where the value is a type with identity, which is not mapped to a simple JSON Schema type. Otherwise the value is always encoded inline.
Note
|
Some applications may prefer to reference types with identity using a code (of type string or number) instead of using a URI. That code could be seen as a foreign key. In such cases, a model transformation should be applied first, which, for all properties whose value type is a type with identity, replaces the value type with CharacterString or Number. The ShapeChange TypeConverter transformer could be enhanced to support such a transformation. |
Note
|
Current conversion behavior for value types does not enable by reference encoding for value types that are data types. In general, a data type does not have identity, and therefore a data type value should always be encoded inline, not by reference. The XML Schema encoding rule defined by ISO 19139:2007, typically used to encode metadata schemas (as defined by ISO 19115, and extensions thereof), on the other hand, allows by reference encoding for data type values. When comparing the previous version of ISO 19115 (from 2003/2006) against the current version (from 2014), we can see that some classes that were defined as data types in the previous version are now defined as object types, for example CI_Citation. This indicates that the assignment of the <<dataType>> stereotype has been corrected, in order to reflect in the conceptual model that the type shall be a type with identity. |
Note
|
If specialization needed to be supported (for further details, see section Class Specialization and Property Ranges), then the logic for determining the value type would need to be extended, to cover cases where the value type is a supertype. A particular example of such a situation can be found in the NAS, where an ISO type is used as value type, with the NAS actually defining a subtype of that ISO type. |
6.2.4.2. Multiplicity
If the minimum cardinality of a UML property is 1 or greater, then the property will be listed under the "required" properties of the object to which the property belongs.
Note
|
Specific conversion rules may override this behavior, for example the rules for converting a <<union>> (see section Union). |
In addition, if the maximum cardinality of the property is greater than 1, then a JSON Schema will be created for the property as follows.
-
The "type" of the JSON property is set to "array", with the "items" keyword containing the JSON Schema constraints that are created to represent the value type of the property.
-
If the minimum cardinality is greater than 0, it is encoded using the "minItems" keyword.
-
If the maximum cardinality is not unbounded, it is encoded using the "maxItems" keyword.
-
If the values of the property must be unique (which is the default for UML properties), then that is represented by adding
"uniqueItems": true
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Type": {
"type": "object",
"properties": {
"property": {
"type": "array",
"minItems": 1,
"maxItems": 2,
"items": {
"type": "string"
},
"uniqueItems": true
}
},
"required": [
"property"
]
}
},
"$ref": "#/definitions/Type"
}
This JSON object is valid against the schema from Listing 22:
1
2
3
{
"property": ["a","b"]
}
This JSON object is invalid (because "property" has three values, which exceeds the maximum amount of allowed values) against the schema from Listing 22:
1
2
3
{
"property": ["a","b",""]
}
Note
|
All arrays in JSON are ordered, thus that the values of a UML property are ordered is always represented, and that the values of such a property are unordered cannot be represented. However, the latter should not matter to an application that does not expect ordered values for a certain property. |
Note
|
An alternative approach for encoding a UML property with maximum multiplicity greater than one and a minimum multiplicity of 0 or 1 would be to allow either the type or an array of the type, so that a single value does not need to be encoded as an array. However, it is unclear if JSON tools generally support such an approach, i.e., encoding JSON member values as either a single value or within an array. Therefore, no conversion rule to support the alternative approach has been defined yet. |
6.2.4.3. Voidable
With rule-json-prop-voidable, the JSON Schema of a UML property with stereotype <<voidable>>, or with tagged value nillable = true, is defined in a way that only allows either a null value or a(n array of) actual value(s).
-
If the UML property has maximum multiplicity 1, then a simple "type" restriction with value "null" is added to the type definition that is produced for the property.
-
Otherwise - the maximum multiplicity is greater than 1 - a choice (encoded using the "oneOf" keyword) between a "null" value and an array of actual values will be created.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Type1": {
"type": "object",
"properties": {
"propertyA": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/definitions/Type2"
}
]
}
},
"required": [
"propertyA"
]
},
"Type2": {
"type": "object",
"properties": {
"propertyB": {
"type": "string"
}
},
"required": [
"propertyB"
]
}
},
"$ref": "#/definitions/Type1"
}
The following two JSON objects are valid against the schema from Listing 23:
1
2
3
{
"propertyA": null
}
1
2
3
4
5
{
"propertyA": {
"propertyB": "x"
}
}
This JSON object is invalid (because "propertyB" is not allowed to be null) against the schema from Listing 23:
1
2
3
4
5
{
"propertyA": {
"propertyB": null
}
}
If propertyA from the example shown in Figure 13 had maximum multiplicity of "*", then the resulting JSON Schema would be as in Listing 24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Type1": {
"type": "object",
"properties": {
"propertyA": {
"oneOf": [
{
"type": "null"
},
{
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/Type2"
},
"uniqueItems": true
}
]
}
},
"required": [
"propertyA"
]
},
"Type2": {
"type": "object",
"properties": {
"propertyB": {
"type": "string"
}
},
"required": [
"propertyB"
]
}
},
"$ref": "#/definitions/Type1"
}
To encode the nil/null reason a separate, parallel property "xyz_nilReason" (or similar) could be added. This is implemented using a new transformation, not as part of the JSON Schema encoding rule.
6.2.4.4. Fixed / readOnly
With rule-json-prop-readOnly, the JSON Schema definition of a UML property that is read only or fixed will include the "readOnly" annotation with JSON value true.
Note
|
With rule-json-prop-derivedAsReadOnly, a UML property marked as derived will also be encoded with "readOnly": true .
|
6.2.4.5. Initial Value
With rule-json-prop-initialValueAsDefault, the JSON Schema definition of a UML attribute that has an initial value, is not owned by an enumeration or code list, and whose value type is mapped to "string", "number", or "boolean", will include the "default" annotation with that value.
Note
|
The value of the annotation can have any JSON value type. The initial value is encoded accordingly: quoted, if the property type is "string", unquoted if the property type is "number", and true if the property type is "boolean" and the initial value is equal to, ignoring case, "true"; otherwise the value will be false. Theoretically, the default value can also be a JSON array or object, but that cannot be represented in UML and thus is not a relevant use case. |
6.2.5. Association Class
There is no native represention for association classes in JSON or JSON Schema. For schemas that include association classes, a transformation of association classes as defined by GML 3.3 and implemented by the ShapeChange Association Class Mapper should be used.
6.2.6. Constraints
OCL constraints can be used to enrich a conceptual model with requirements that cannot be expressed in UML alone. A full analysis of options for converting OCL expressions to something with which JSON data can be checked is out-of-scope for UGAS-2020, and therefore future work.
However, a particular type of OCL constraint defined in the NAS has been identified as critical for achieving a useful JSON Schema encoding of the NAS in UGAS-2020: constraints that disallow related entity types. Figure 14 provides an example.
The value type of property place is the abstract type PlaceSpecification. That type is the root of an inheritance hierarchy, which contains four non-abstract classes. With typical UML semantics, the value of place can thus be any non-abstract subtype of PlaceSpecification. In the given example, that would be one of the types PointPositionSpecification, CurvePositionSpecification, SurfacePositionSpecification, and LocationSpecification. Note that further characteristics of these types, e.g., UML properties, have been omitted for brevity.
Diagram notes attached to the feature types FT1 and FT2 indicate that only a subset of non-abstract PlaceSpecification subtypes are actually allowed as value of property place. The according OCL constraints are defined as follows:
-
FT1 - OCL constraint "Place Representations Disallowed":
inv: place→forAll(p| not(p.oclIsKindOf(CurvePositionSpecification) or p.oclIsKindOf(SurfacePositionSpecification)))
-
FT2 - OCL constraint "Place Representations Disallowed":
inv: place→forAll(p| not(p.oclIsKindOf(CurvePositionSpecification) or p.oclIsKindOf(SurfacePositionSpecification) or p.oclIsKindOf(LocationSpecification)))
Note
|
Because the OCL constraint of FT2 has the same name as that of FT1, it overwrites the constraint that would be inherited from FT1. |
In order to realize the value type restriction defined by such an OCL constraint, a model transformation - described in section Transforming OCL Constraints Defining Value Type Restrictions has been added to ShapeChange. In short, the transformation determines which value types are allowed for a UML property of a class (given that a value type restriction is defined for that property), and adds information about the allowed types to the model using a tagged value. That tagged value is used by rule-json-cls-valueTypeOptions (see section Value Type) to encode the value type restriction in JSON Schema.
Note
|
The model transformation also determines if the property is an association role whose association actually is an association class. If so, that information is added to the tagged value. As described in section Association Class, JSON Schema cannot directly represent association classes, and therefore such model constructs need to be transformed as defined by the GML 3.3 encoding rules. The resulting model structure is taken into account by rule-json-cls-valueTypeOptions, as shown in the following example. |
Listing 25 shows how the value type restrictions for property place in the example used in this section are encoded in JSON Schema, assuming an inline encoding of place to achieve a more simple JSON Schema example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$defs": {
"CurvePositionSpecification": { ... },
"FeaturePlaceRelationship": {
"$anchor": "FeaturePlaceRelationship",
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"place": {
"$ref": "#/$defs/PlaceSpecification"
}
},
"required": [
"@type",
"place"
]
},
"LocationSpecification": { ... },
"PlaceSpecification": { ... },
"PointPositionSpecification": { ... },
"PositionSpecification": { ... },
"SurfacePositionSpecification": { ... },
"FT1": {
"$anchor": "FT1",
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"place": {
"oneOf": [
{
"type": "null"
},
{
"allOf": [
{
"$ref": "#/$defs/FeaturePlaceRelationship"
},
{
"type": "object",
"properties": {
"place": {
"if": {
"properties": {
"@type": {
"const": "LocationSpecification"
}
}
},
"then": {
"$ref": "#/$defs/LocationSpecification"
},
"else": {
"if": {
"properties": {
"@type": {
"const": "PointPositionSpecification"
}
}
},
"then": {
"$ref": "#/$defs/PointPositionSpecification"
},
"else": false
}
}
}
}
]
}
]
}
},
"required": [
"@type",
"place"
]
},
"FT2": {
"$anchor": "FT2",
"allOf": [
{
"$ref": "#/$defs/FT1"
},
{
"type": "object",
"properties": {
"place": {
"oneOf": [
{
"type": "null"
},
{
"allOf": [
{
"$ref": "#/$defs/FeaturePlaceRelationship"
},
{
"type": "object",
"properties": {
"place": {
"if": {
"properties": {
"@type": {
"const": "PointPositionSpecification"
}
}
},
"then": {
"$ref": "#/$defs/PointPositionSpecification"
},
"else": false
}
}
}
]
}
]
}
}
}
]
}
},
"$ref": "#/$defs/FT2"
}
The following JSON object is valid against the schema for FT2.
1
2
3
4
5
6
7
8
9
{
"@type": "FT2",
"place": {
"@type" : "FeaturePlaceRelationship",
"place": {
"@type": "PointPositionSpecification"
}
}
}
The next JSON object is invalid against the schema for FT2, because the @type of the PlaceSpecification object that is the value of the FeaturePlaceRelationship.place property is LocationSpecification - which is allowed for FT1, but not for FT2.
1
2
3
4
5
6
7
8
9
{
"@type": "FT2",
"place": {
"@type" : "FeaturePlaceRelationship",
"place": {
"@type": "LocationSpecification"
}
}
}
Note
|
That place is a mandatory property results in "place" being added to the "required" member of the JSON Schema for FT1. There is no need to repeat this requirement in the encoding of FT2. However, other definitions would need to be repeated to achieve a consistent JSON Schema, such as that the value of the property is an array (if maximum multiplicity of the property is greater than 1), and that a null value is allowed (if the property is voidable). |
6.2.7. Additional rules
If rule-json-all-notEncoded applies to an element of the application schema, then that element and all its components are not encoded.
Note
|
How to define the encoding rule that applies to an application schema element is documented in more detail here. The ShapeChange configuration file StandardRules.xml defines an encoding rule named "notEncoded", which includes rule-json-all-notEncoded. When StandardRules.xml is included in the configuration of the JSON Schema target (typically using an xinclude XML element), then by setting tagged value jsonEncodingRule to "notEncoded", one would achieve that that model element is not encoded in the JSON Schema. |
6.3. Instance Conversion Rules
This section documents recommendations and relevant aspects for encoding geospatial data in JSON.
6.3.1. Coordinate Reference System in JSON data
The GeoJSON standard requires that all GeoJSON coordinates use urn:ogc:def:crs:OGC::CRS84 as coordinate reference system (CRS), with optional height in meters above or below the WGS 84 reference ellipsoid. Alternative CRSs are not allowed by this standard.
The OGC API - Features - Part 1: Core standard essentially has the same requirement:
Unless the client explicitly requests a different coordinate reference system, all spatial geometries SHALL be in the coordinate reference system http://www.opengis.net/def/crs/OGC/1.3/CRS84 (WGS 84 longitude/latitude) for geometries without height information and http://www.opengis.net/def/crs/OGC/0/CRS84h (WGS 84 longitude/latitude plus ellipsoidal height) for geometries with height information.
A previous version of the GeoJSON standard did allow alternative CRSs, but that option has been removed "because the use of different coordinate reference systems has proven to have interoperability issues" (GeoJSON standard, chapter 4). However, the GeoJSON standard also states that if all involved parties have a prior arrangement, then alternative CRSs can be used.
The OGC API - Features - Part 1: Core standard also does not preclude the use of additional CRSs, but does not specify how to request features in such reference systems. That is the purpose of OGC API - Features - Part 2: Coordinate Reference Systems by Reference, which is currently under development.
To summarize: Coordinates of GeoJSON compliant data as well as spatial data accessed using the OGC API - Features standard must be given in OGC CRS84 (with optional height). That has implications for data publishers and consumers. A major benefit is increased interoperability, because spatial datasets that use the same CRS can easily be merged. If a use case requires other CRSs, then both GeoJSON and the OGC API - Features standards have options to support that. Data publisher and consumer only need to agree on the CRS in which the coordinates of spatial data, that is being exchanged between the two, is given in.
6.4. Conceptual Model Transformation Rules
The conceptual schema may need to be transformed, in order to deal with model elements:
-
that cannot be represented in JSON at all (e.g., association classes);
-
that cannot be represented in a certain JSON format (e.g., a Solid - a 3D geometry type - as value for the "geometry" member of a GeoJSON feature); or
-
that are not (well) supported by client software (e.g., complex attribute values for styling, processing, and filtering).
The following sections describe model transformations that can be useful to deal with these restrictions when encoding application schemas as JSON Schemas.
6.4.1. Flattening Inheritance
As mentioned in section Inheritance, JSON Schema does not directly support the concept of inheritance. There are ways to represent inheritance in JSON Schema to a certain extent. Generalization can be represented using an "allOf" that includes the schema of a subtype and the schema(s) of its supertype(s). Specialization can be represented as a relatively complex if-then-else construct, with which JSON objects - that encode types from a type hierarchy) can be validated based upon a property value that declares their type.
If a community does not want to apply these solutions for representing inheritance in JSON Schema, but still wants to use inheritance in their concpetual model and derive a JSON Schema encoding from it, then inheritance needs to be transformed on the conceptual level. Generalization (in the sense of Class Generalization and Property Inheritance) would be transformed by copying all properties of a supertype down to direct and indirect subtypes. For each supertype, a union of the non-abstract types in the hierarchy of that supertype (including the supertype itself) would be created, and the value type of each property that is that supertype would be switched to the union. That would allow the encoding of subtypes, instead of the supertype, as property value - and thus support specialization (in the sense of Class Specialization and Property Ranges).
The transformation of inheritance is implemented by the ShapeChange Flattener transformer, in rule-trf-cls-flatten-inheritance. The documentation of the rule provides further details.
Note
|
The introduction of new unions as value types, for properties that have a supertype as value type, creates a level of indirection that may not be desirable. One approach to avoid the indirection would be to flatten the unions using another transformation, i.e., Flattening Complex Types (though that would create additional properties and remove the union semantics). Another approach would be to encode these unions as object references. This approach has been used in the creation of a GML-SF Level 0 XML Schema in OGC Testbed 13 (for further details, see the OGC Testbed-13: NAS Profiling Engineering Report, section 7.2.19. XML Schema encoding, rule-xsd-cls-union-omitUnionsRepresentingFeatureTypeSets. |
6.4.2. Flattening Multiplicity
Simple JSON formats may not support properties with a maximum multiplicity greater than 1. If the conceptual model contains such properties, they can be transformed to a set of properties, each with maximum multiplicity = 1.
This kind of model transformation is implemented in ShapeChange by rule-trf-prop-flatten-multiplicity of the Flattener transformer.
6.4.3. Flattening Complex Types
A community may want to keep their JSON formats simple by not allowing nested objects within a JSON object, or only a bare minimum (e.g., when their JSON shall be GeoJSON compliant). In such a case, nested objects that represent data types and unions from the conceptual model must be avoided. At the same time, the JSON formats used by the community must still be able to represent the information items that would usually be encoded via these complex types.
rule-trf-prop-flatten-types, implemented by the ShapeChange Flattener transformer, "flattens" these complex types by copying their properties to the types that use the complex types. The names of the property copies are modified to reflect which information items they represent.
6.4.4. Mapping Association Classes
JSON Schema cannot directly represent association classes. An association class therefore needs to be transformed into a structure that can be represented with JSON Schema. The transformation of association classes defined by GML 3.3 is a suitable solution.
The ShapeChange Association Class Mapper implements the transformation defined by GML 3.3.
6.4.5. Transforming Stereotype <<propertyMetadata>>
In the UGAS-2019 OGC Pilot, the <<propertyMetadata>> stereotype was developed. When assigned to a property, it indicates that the property can be associated with metadata. The metadata would provide additional information on the property value or values. Tagged value metadataType is defined for the stereotype, and used to identify the actual type that the property references as metadata.
The Property Stereotype for Metadata document describes how the stereotype is encoded in XML Schema. Basically, a "metadata" XML attribute is added on the XML element that represent the property. The XML attribute can be used to reference the metadata object, much like an "xlink:href" XML attribute would be used to reference a "normal" object.
Some encodings - like JSON - do not have anything similar to XML attributes. Section 2.3.2 of the Property Stereotype for Metadata document describes how the <<propertyMetadata>> stereotype can be handled in such an encoding. In essence, the stereotype is transformed to an additional property, with the type identified by tagged value metadataType as value type.
The transformation is implemented by the ShapeChange Type Converter transformer in rule-trf-propertyMetadata-stereotype-to-metadata-property.
-
Rule behavior: Converts the <<propertyMetadata>> stereotype to an additional property, as follows: First, the metadata type that applies to the property with the stereotype is identified: The tagged value metadataType of the property is checked first. If the tagged value does not identify a metadata type, then the type defined by configuration parameter defaultMetadataType is used.
NoteThe identification of the metadata type by tagged value or by configuration parameter is as follows:
-
definition by tagged value metadataType: If the type is defined by the schema that contains the property, then the tagged value simply provides the name of the type. Otherwise, the tagged value shall identify the type by its full package-qualified name, starting with the application schema package. For example: "Some Application Schema::Some Subpackage::Another Subpackage::MetadataType."
-
definition by configuration parameter defaultMetadataType: If the name of the type is unique within the conceptual model, then simply providing the type name as parameter value is sufficient. Otherwise (or as a general alternative), the metadata type is identified by providing its full name (omitting packages that are outside of the schema the class belongs to - see the example above).
If the configuration parameter also does not identify a type within the conceptual model, an error message will be logged and the stereotype will simply be removed from the property. Otherwise, if the metadata type is a type with identity (feature or object type) then a directed association to the metadata type is created - else an attribute (with the metadatatype as value type) is created. The name of the new association role or attribute is the property name plus suffix defined by configuration parameter metadataPropertyNameSuffix. If a new association role was created, tagged value inlineOrByReference of the association role is set to the value defined by configuration parameter metadataPropertyInlineOrByReference. Otherwise, i.e., an attribute was created, tagged value inlineOrByReference is set to "inline." Tagged value sequenceNumber will be set in such a way that the new property is placed directly after the original property.
-
-
Configuration parameter defaultMetadataType: Name of the type from the conceptual model, which shall be used as metadata type for all properties with stereotype <<propertyMetadata>> that do not define a metadata type via tagged value metadataType. The value can be the pure type name, if it is unique within the conceptual model. Otherwise, the correct type is identified by providing its full name (omitting packages that are outside of the schema the class belongs to). The default value for this parameter is 'MD_Metadata' (which typically refers to the type defined by ISO 19115).
-
Configuration parameter metadataPropertyNameSuffix: Defines the suffix that shall be added to the name of a new property created by rule-trf-propertyMetadata-stereotype-to-metadata-property. Default is'_metadata'.
-
Configuration prameter metadataPropertyInlineOrByReference: Defines the value for tag inlineOrByReference of a new association role created by rule-trf-propertyMetadata-stereotype-to-metadata-property. Default is 'inlineOrByReference'. Other allowed values are 'byReference' and 'inline'.
6.4.6. Generating NilReason Properties for Nillable Properties
A UML property that is defined for a feature, object, data, or union type within an application schema, by default cannot have a null value. In order to model that a property can have a null value (instead of actual value(s)), stereotype <<voidable>> must be added to the property, or tagged value nillable with value 'true'. Such a property is called a nillable property.
The recommendation from the UGAS-2019 OGC Pilot for NAS modelling of nillable properties (for further details, see the Property Stereotype for Metadata document, section 2.2) is to use the <<voidable>> stereotype, and to also set tagged value voidReasonType on the property, in order to define the enumeration that defines the reasons for a null value.
In the XML Schema encoding, nillable properties are represented by XML elements for which the XML attribute "nilReason" can be set. As also mentioned in section Transforming Stereotype <<propertyMetadata>>, some encodings - like JSON - do not have anything similar to XML attributes. In order to encode the reason why a nillable property has a null value in such an encoding, the application schema can be transformed, adding a new property for each nillable property (to the class that owns the nillable property), with the new property having the void reason type as value type.
The according transformation is implemented by the ShapeChange Type Converter transformer in rule-trf-nilReason-property-for-nillable-property.
-
Rule behavior: For each property that is nillable (has stereotype <<voidable>> or tagged value nillable set to 'true'), create a new attribute, as follows: First, the void reason type that applies to the nillable property is identified: The tagged value voidReasonType of the nillable property is checked first. If the tagged value does not exist or does not identify a type, then the type defined by configuration parameter defaultVoidReasonType is used.
NoteThe identification of the void reason type by tagged value or by configuration parameter is as follows.
-
Definition by tagged value voidReasonType: If the type is defined by the schema that contains the property, then the tagged value simply provides the name of the type. Otherwise, the tagged value shall identify the type by its full package-qualified name, starting with the application schema package. For example: "Some Application Schema::Some Subpackage::Another Subpackage::VoidReasonType".
-
Definition by configuration parameter defaultVoidReasonType: If the name of the type is unique within the conceptual model, then simply providing the type name as parameter value is sufficient. Otherwise (or as a general alternative), the void reason type is identified by providing its full name (omitting packages that are outside of the schema the class belongs to - see the example above).
If the configuration parameter also is not set or does not identify a type within the conceptual model, an error message will be logged and the value type of the new attribute will be CharacterString. Otherwise, the identified type will be set as value type of the new attribute. The name of the new attribute is the name of the nillable property plus suffix defined by configuration parameter nilReasonPropertyNameSuffix. Tagged value inlineOrByReference of the new attribute is set to inline. Tagged value sequenceNumber will be set in such a way that it is placed directly after the nillable property.
-
-
Configuration parameter defaultVoidReasonType: Name of the type from the conceptual model, which shall be used as void reason type for all nillable properties that do not define a void reason type via tagged value voidReasonType. The value can be the pure type name, if it is unique within the conceptual model. Otherwise, identify the correct type by providing its full name (omitting packages that are outside of the schema the class belongs to). No default value is defined for this parameter.
-
Configuration parameter nilReasonPropertyNameSuffix: Defines the suffix that shall be added to the name of a new property created by rule-trf-nilReason-property-for-nillable-property. Default is'_nilReason'.
6.4.7. Transforming OCL Constraints Defining Value Type Restrictions
An OCL constraint such as inv: place→forAll(p|not(p.oclIsKindOf(CurvePositionSpecification) or p.oclIsKindOf(SurfacePositionSpecification)))
, and - for the sake of the example used in this section - name "Value Type Representations Disallowed", restricts the set of allowed value types for a property. In the example, property place must not have a value of type CurvePositionSpecification or SurfacePositionSpecification. The example is described in more detail in section Constraints.
With rule-trf-cls-constraints-valueTypeRestrictionToTV-exclusion - defined for the ShapeChange ConstraintConverter transformation, the value type restrictions defined by OCL constraints can be extracted from the OCL expression, and converted into a tagged value, to be used by subsequent transformation and conversion processes.
Configuration parameter valueTypeRepresentationConstraintRegex is used to identify the relevant OCL constraints. The parameter value contains a regular expression - for example .*Value Type Representations Disallowed.*
, which matches the names of OCL constraints that define value type restrictions. The according OCL expressions must thereby be structured as in the example (with oclIsTypeOf(..) also being supported).
The name of the property that is restricted is parsed from the begin of the OCL expression: inv: {propertyName}->forAll
… The property name may thereby be preceded by self.
, i.e., inv: self.{propertyName}->forAll
… is a valid alternative way to structure the value type restricting OCL expression.
Required configuration parameter valueTypeRepresentationTypes specifies the types that are used as value type by the UML properties identified in the value type restricting OCL constraints. For each such type, a list of names of the generally allowed types within the inheritance hierarchy of that type must be provided, which may include the type itself and abstract types. For example, for the value type PlaceSpecification of property place shown in Figure 14, the value of the configuration parameter could be: PlaceSpecification{PointPositionSpecification, CurvePositionSpecification, SurfacePositionSpecification, LocationSpecification}
. The transformation will automatically add all subtypes of generally allowed types to the set of generally allowed types. That is important for creating a tagged value that explicitly lists the types that are allowed for a property, regardless of inheritance structures, because the OCL constraint may exclude a specific subtype of a generally allowed supertype.
Note
|
If multiple value types need to be described by configuration parameter valueTypeRepresentationTypes, then a semicolon is used to separate the descriptions in the parameter value. |
The transformation will parse a value type restricting OCL constraint in order to determine the (potentially inherited) UML property to which the constraint applies. The OCL expression is structured so that any type mentioned in the expression is disallowed/excluded. The transformation can therefore determine the value types that are disallowed - also taking into account all subtypes of a type that is mentioned within an oclIsKindOf(..). The set of disallowed types will then be subtracted from the set of generally allowed types, resulting in the set of types that are allowed as value types of the property.
The allowed types for the property are documented in the model by adding (also: overwriting, if it already exists) tagged value valueTypeOptions to the class on which the UML property is defined. The tagged value is structured as follows:
{propertyName}(\(associationClassRole\))?={allowedTypeName}(,{allowedTypeName})(;{propertyName}(\(associationClassRole\))?={allowedTypeName}(,{allowedTypeName}))*
For the example OCL constraint, that would result in: place(associationClassRole)=PointPositionSpecification,LocationSpecification
.
Note
|
The example shows that the tagged value may contain a qualifier - associationClassRole - for a property, which, if set, indicates that the property is an association role whose association actually is an association class. That information can be relevant for subsequent processes, for example the JSON Schema encoding, when a previous model transformation has transformed association classes as defined by the GML 3.3 encoding rules. |
Note
|
Configuration parameter valueTypeRepresentationTypes can also define an alias for the name of an allowed type. For example: PlaceSpecification{PointPositionSpecification=P, CurvePositionSpecification=C, SurfacePositionSpecification=S, LocationSpecification=L} . The alias is used when constructing tagged value valueTypeOptions. That can be useful in case that the names of UML types contained in the model are flattened, i.e., replaced by a short name or code, by a subsequent model transformation. Processes that convert such a flattened model and use the information from tagged value valueTypeOptions then have the correct names of allowed value types.
|
6.5. Encoding Rules
This section documents two JSON Schema encoding rules, one for achieving a GeoJSON compliant JSON Schema encoding, and one for producing plain JSON Schemas (typically for non-geospatial schemas).
Note
|
Each of these two rules is implemented in ShapeChange, the first with name "defaultGeoJson", and the second with name "defaultPlainJson". Additional conversion rules can easily be added to such an encoding rule by defining a new encoding rule in the ShapeChange JSON Schema target that extends "defaultGeoJson" or "defaultPlainJson", and setting the new rule as the default encoding rule (using the ShapeChange JSON Schema target parameter defaultEncodingRule). If, on the other hand, conversion rules from "defaultGeoJson" or "defaultPlainJson" need to be removed or replaced, for any reason, then these encoding rules cannot be used (ShapeChange supports extending a named encoding rule, but not restricting it), and instead a new encoding rule must be defined that is patterned after the applicable existing rule. |
Note
|
For some application schemas, it is useful to know that different encoding rules can be applied to the subpackages, classes, and properties defined by the schema. Typically, a single encoding rule applies to all application schema elements. In ShapeChange, that rule is identified by setting the JSON Schema target parameter defaultEncodingRule, with the unique name defined for the encoding rule in the target configuration. The target configuration, however, can contain multiple encoding rules (with different names). By setting tagged value jsonEncodingRule on an application schema element, using the name of another encoding rule, the model element will be encoded as defined by that rule. For example, if an application schema used unions in both ways described in section Union, then the default encoding rule could include rule-json-cls-union-propertyCount, and encoding rule "TypeDiscriminatorUnionRule" could instead include rule-json-cls-union-typeDiscriminator. By setting tagged value jsonEncodingRule=TypeDiscriminatorUnionRule on each type discriminator union, these unions would be encoded using rule-json-cls-union-typeDiscriminator and all other unions would be encoded using rule-json-cls-union-propertyCount. |
6.5.1. GeoJSON Schema Encoding Rule
In order to achieve a GeoJSON compliant encoding using ShapeChange, set "defaultGeoJson" as the default encoding rule for the JSON Schema target (using the target parameter defaultEncodingRule).
This encoding rule consists of the following conversion rules:
-
rule-json-cls-defaultGeometry-singleGeometryProperty
-
rule-json-cls-ignoreIdentifier
-
rule-json-cls-name-as-anchor
-
rule-json-cls-nestedProperties
-
rule-json-cls-virtualGeneralization
-
rule-json-prop-derivedAsReadOnly
-
rule-json-prop-initialValueAsDefault
-
rule-json-prop-readOnly
-
rule-json-prop-voidable
Furthermore, the following parameters need to be added to the configuration of the ShapeChange JSON Schema target:
-
baseJsonSchemaDefinitionForFeatureTypes = https://geojson.org/schema/Feature.json
-
baseJsonSchemaDefinitionForObjectTypes = https://geojson.org/schema/Feature.json
Geometry types used in the conceptual model (e.g., types from ISO 19107) must be mapped to one of the GeoJSON geometry types (see Table 5).
Conceptual geometry type | GeoJSON geometry type |
---|---|
GM_Point |
|
GM_Curve |
|
GM_Surface |
|
GM_MultiPoint |
|
GM_MultiCurve |
|
GM_MultiSurface |
|
GM_Object |
Note
|
In order to achieve an OGC JSON encoding, the ShapeChange JSON Schema target parameters baseJsonSchemaDefinitionForFeatureTypes and baseJsonSchemaDefinitionForObjectTypes would have to be set to reference the schema for AnyFeature, shown in Listing 57. Furthermore, the geometry types would need to be mapped as defined in Table 8. |
The feature type illustrated in Figure 15 is used as example for a GeoJSON based encoding, which is shown in Listing 26.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"TypeG": {
"$id": "#TypeG",
"allOf": [
{
"$ref": "https://geojson.org/schema/Feature.json"
},
{
"type": "object",
"properties": {
"properties": {
"type": "object",
"properties": {
"propertyG": {
"type": "number"
}
},
"required": [
"propertyG"
]
},
"geometry": {
"$ref": "http://geojson.org/schema/Point.json"
}
},
"required": [
"properties"
]
}
]
}
},
"$ref": "#/definitions/TypeG"
}
This JSON object is valid against the schema from Listing 26:
1
2
3
4
5
6
7
8
9
10
11
{
"id": "42445fdasd7asd6f7",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [8.195669, 51.903589]
},
"properties": {
"propertyG": 3
}
}
This JSON object is invalid against the schema from Listing 26 (because the JSON value of "geometry" is not valid according to the JSON Schema of a GeoJSON point):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"id": "42445fdasd7asd6f7",
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[102.0,0.0],
[103.0,1.0],
[104.0,0.0],
[105.0,1.0]
]
},
"properties": {
"propertyG": 3
}
}
6.5.2. Plain JSON Schema Encoding Rule
Some communities have schemas where "geospatial" plays a minor or no role at all. For such cases, the use of GeoJSON features is not relevant. The property nesting and the restrictions of the "type" and "geometry" members defined by the GeoJSON schema could even be a hindrance.
In order to achieve a plain JSON Schema encoding using ShapeChange, set "defaultPlainJson" as the default encoding rule for the JSON Schema target (using the target parameter defaultEncodingRule).
This encoding rule consists of the following conversion rules:
-
rule-json-cls-name-as-anchor
-
rule-json-prop-derivedAsReadOnly
-
rule-json-prop-initialValueAsDefault
-
rule-json-prop-readOnly
-
rule-json-prop-voidable
The geometry types used in the conceptual model should be mapped to the JSON Schema implementations defined by the Features Core Profile.
A plain JSON Schema encoding of the feature type that was used as example for the GeoJSON based encoding in the previous section (see Figure 15) is shown in Listing 27.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"TypeG": {
"$id": "#TypeG",
"type": "object",
"properties": {
"location": {
"$ref": "http://geojson.org/schema/Point.json"
},
"propertyG": {
"type": "number"
}
},
"required": [
"location",
"propertyG"
]
}
},
"$ref": "#/definitions/TypeG"
}
This JSON object is valid against the schema from Listing 27:
1
2
3
4
5
6
7
8
9
10
{
"location": {
"type": "Point",
"coordinates": [
8.195669,
51.903589
]
},
"propertyG": 3
}
7. Features Core Profile of Key Community Conceptual Schemas
7.1. Overview
Most application schemas for geospatial information, including the NAS, build on the comprehensive conceptual schemas from the OGC Abstract Specifications and the ISO 19100 series. This creates a challenge for JSON encodings of those application schemas. XML encodings can build on GML, the ISO-19139-based XML schemas for the metadata standards and the available tools supporting these schemas and standards, but only very few of the classes in the conceptual schemas have associated JSON schemas or JSON support in implementations. While the work documented in chapter UML to JSON Schema Encoding Rule provides the capability to create JSON schemas for the content defined in the application schema packages, JSON schemas for the classes that are imported from other ISO/OGC schemas do not exist yet and therefore cannot be referenced.
Existing JSON encodings for ISO/OGC schemas include the following.
-
Features: GeoJSON and Esri JSON implement features and feature collections, although with limitations, for example, only one geometry property per feature. GeoJSON has a JSON schema and very good tool support. Esri JSON is also widely used in the ArcGIS platform; however, no official JSON schema exists.
-
Spatial geometries: GeoJSON and Esri JSON implement the simple feature geometries. GeoJSON is essentially restricted to WGS84.
-
Coordinate reference systems: PROJJSON is a JSON encoding of WKT2:2019 / ISO-19162:2019, which itself implements the model of OGC Topic 2: Referencing by coordinates, supported by the frequently used PROJ library.
-
SWE Common: A JSON encoding exists as an OGC Best Practice document, but without JSON schema. One implementation is known.
No known JSON schemas exist for other schemas, in particular the metadata and data quality schemas (ISO 19115-1, ISO 19115-2, ISO 19157), for additional spatial geometries beyond Simple Features (ISO 19107) or how time instances and intervals (ISO 19108) should be represented in features consistent with the General Feature Model (ISO 19109).
In order to specify a JSON encoding for the NAS or other application schemas, additional JSON schemas for the imported classes from base schemas defined by ISO/OGC are required.
At the same time, these base schemas are comprehensive and full support requires a significant implementation effort that is often difficult to justify since in practice only a small subset of the complete schema(s) are needed or used. For example, while Geography Markup Language (GML) implements only a subset of all curve segments or surface patches specified by ISO 19107, it is still a comprehensive subset and most of that subset is not, or is only very rarely, used in practice. To address this, the GML Simple Features Profile has been specified to identify a small subset that is sufficient for most use cases. Likewise, many of the metadata elements specified in the ISO 19115-3 XML encoding standards are optional and not used in most metadata XML instance documents – and most communities have defined profiles of the comprehensive ISO metadata schemas to meet their narrower requirements.
Historically it has been the case that defining complete implementation schemas in XML Schema for these ISO standards, and then specifying a multiplicity of community-specific simpler, tailored profiles has limited the extent to which those complete implementation schemas are supported in software and thus contribute to effective interoperability.
Consistent with the approach taken by most of the recent OGC standards, any approach to generating JSON schemas for the base standards should start with a small core encoding of the classes supported by most datasets and implementations. Once proven in practice through implementations, the core can be extended based on community needs.
The definition of this core in the UGAS-2020 pilot has been based on this context. The profile is, therefore, called the "Features Core Profile of Key Community Conceptual Schemas", from now on simply called "Features Core Profile."
The NAS requirements with respect to spatial geometries, temporal information and metadata as it is typically included in existing NAS data (to the extent that this information is publicly available) have been taken into account.
The definition of the JSON schemas for the Features Core Profile has considered existing encodings as a starting point, where they exist, as well as the JSON encoding rule, but with optimizations for the data representation in JSON, similar to how gml:posList is an optimized XML implementation of a GM_PointArray from ISO 19107.
7.2. Scope of the Features Core Profile
Three categories of classes are used by almost all geospatial application schemas, including the NAS.
-
Basic types defined by ISO 19103 - especially literal types for representing values such as CharacterString, Integer, Real, Boolean, Date, and DateTime. In addition, Measure and Any are frequently used, too.
-
Spatial types defined by ISO 19107 – especially geometry types such as GM_Point, GM_Curve, and GM_Surface.
NoteThe NAS baseline X-3 conceptual model does not directly contain ISO 19107. However, a relationship to the schema indirectly exists, through the conceptual schema for elements from ISO 19136. Table 8 defines a mapping between types from ISO 19107 and their counterparts in the ISO 19136 schema contained in the NAS conceptual model. -
Most spatial data has a temporal aspect, too. This may be represented using literal values (Date, DateTime) or using the temporal types defined by ISO 19108 - especially temporal geometry types such as TM_Instant and TM_Period.
The Features Core Profile is comprised of key types from these schemas – see Table 7, Table 8, and Table 9. This set of types represents a small, but useful basis for building geospatial applications that exchange and process JSON encoded spatial data.
For the JSON encoding, the encoding of the feature types based on the General Feature Model defined by ISO 19109 had to be considered as well, building on the discussion in the chapter UML to JSON Schema Encoding Rule. For the Features Core Profile, a consistent approach to encode thematic, spatial, and temporal attributes was required. Since metadata or quality attributes, as well as association roles are also commonly used in application schemas, the JSON feature encoding also includes extensions for those feature property types.
The Features Core Profile does not include classes from the ISO metadata and data quality schemas (ISO 19115-1, 19115-2 and ISO 19157). This has several reasons.
-
Classes from these schemas are less frequently used in geospatial application schemas.
-
In the application schemas where they are used (for example, in the NAS), the profile is often comprehensive and it seems unlikely that a small core that is useful and sufficient for many use cases can be identified.
-
Other conceptual metadata schemas are in broad use that should also be supported. To name a few: Dublin Core, DCAT and schema.org.
The approach taken by the UGAS-2020 pilot therefore was to not include classes from ISO 19115-1, ISO 19115-2 or ISO 19157 in the Features Core Profile, but to specify how JSON instances of those classes could be included in feature and feature collection data.
Nevertheless, application schemas like the NAS have a need to import JSON schemas for classes from these three ISO standards. To support such workflows, Appendix B documents how JSON schemas can be produced for these schemas using ShapeChange and the UML to JSON Schema Encoding Rule. These JSON schemas could be used as-is in a JSON encoding of the NAS or the result could be the starting point for additional optimizations. With such JSON Schemas, as well as the JSON schema definitions for the Features Core Profile, a JSON-Schema-based encoding for the NAS can be produced.
7.3. The Features Core Profile and its encoding in JSON
This section identifies the types from the ISO/TC 211 Harmonized Model that are part of the Features Core Profile.
It also specifies the mapping of these types to JSON Schema. In some cases this mapping is specified as a JSON Schema implementation of the type that can be referenced from an application schema in JSON Schema; these JSON schemas have an "$id" that starts with "http://www.opengis.net/tbd/" and could become part of the schema definitions of a future OGC JSON specification. In other cases, the JSON Schema implementation is always included inline and the mapping extends the UML-to-JSON-Schema encoding rule.
7.3.1. Overview
Table 6 provides an overview of the types from the ISO/TC 211 Harmonized Model included in the Features Core Profile.
Basic types | Spatial types | Temporal types | Feature types |
---|---|---|---|
ISO 19103:2015 |
ISO 19107:2003 |
ISO 19108:2002 |
ISO 19109:2015 |
While the table uses the types from the ISO/TC 211 harmonized model, this is not meant to imply that any valid instance of these types are covered by the profile.
For the purposes of defining a Features Core Profile of spatial types, the representations of all spatial 1d, 2d, and 3d geometric primitives in ISO 19107 and all temporal geometric primitives in ISO 19108 are restricted to the simple representations that are widely supported in software tools and libraries.
The following constraints apply for the spatial geometric primitive types.
-
GM_Curve is constrained to a single curve segment with linear interpolation.
-
GM_Surface is constrained to a single surface patch that is a GM_Polygon with planar interpolation where each ring is a closed GM_Curve.
-
Each shell of a GM_Solid is constrained to be a closed GM_PolyhedralSurface where each patch is a GM_Polygon.
These constraints apply to all instances including geometric primitives that are part of a geometric aggregate.
For ISO 19107:2019, any Collection is constrained to be homogenuous, i.e., it is a collection of geometric primitives of the same dimension.
Note
|
GM_Aggregate has not been included in the profile, since it does not seem to be used much in practice. |
The following constraints apply for the temporal geometric primitive types:
-
TM_Instant and TM_Period are constrained to the temporal positions in the Gregorian calendar.
7.3.2. Basic Types
This section lists the types from ISO 19103 that belong to the Features Core Profile and documents their JSON Schema definition. The following sections provide more detail and specify the JSON encoding.
7.3.2.1. Simple Types
Most of the frequently used basic types are simple, i.e., the value can be represented by a single literal value. The mapping to the JSON Schema types and - where applicable - the JSON Schema format specifier and maybe additional JSON Schema keywords is shown in Table 7.
Type | JSON Schema type | JSON Schema format | Additional JSON Schema validation keyword(s) |
---|---|---|---|
Boolean |
boolean |
||
Character |
string |
"minLength" : 1 and "maxLength" : 1 |
|
CharacterString |
string |
||
Date |
string |
date |
|
DateTime |
string |
date-time |
|
Decimal |
number |
||
Integer |
integer |
||
Number |
number |
||
Real |
number |
||
URI |
string |
uri |
7.3.2.2. Non-simple Types
In addition to the simple types, two additional non-simple types are included in the Features Core Profile since they are frequently used in application schemas:
-
Measure (or any of its subtypes): Measure is a combination of a numeric value and the unit of measurement of the value;
-
Any
7.3.2.2.1. Measure
Three alternative mappings to JSON Schema are specified. In the discussion below we use a property length : Measure [0..1]
as an example.
Default representation
In the default mapping, the property could be represented as an object-valued property in JSON. The object should have two properties, one for the numeric value ("value") and one for the unit ("uom").
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Measure.json",
"title": "A measure",
"type" : "object",
"required" : [ "value", "uom" ],
"properties" : {
"value" : {
"type" : "number"
},
"uom" : {
"type" : "string"
}
}
}
1
2
3
4
5
6
{
"length" : {
"value" : 45.6,
"uom" : "m"
}
}
Listing 28 may be referenced directly from application schemas. However, it may also be desirable to specify constraints on the ranges of "value" and "uom". In that case, the Measure schema can be used as a template that is modified to include the constraints.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"type" : "object",
"required" : [ "value" ],
"properties" : {
"value" : {
"type" : "number",
"minimum" : 0
},
"uom" : {
"type" : "string",
"enum" : [ "m", "ft" ],
"default" : "m"
}
}
}
Fixed units
For cases where the application schema uses a fixed value, the JSON Schema type "number" could be used directly. If desired, a suffix could be added to the name of the property to indicate the fixed unit. In this case, the symbol of the unit should be added, separated with an underscore. Example:
1
2
3
4
5
6
7
8
{
"type" : "object",
"properties" : {
"length_m" : {
"type" : "number"
}
}
}
1
2
3
{
"length_m" : 45.6
}
Flat representation
For cases where the unit of measurement may differ from feature to feature, where the maximum multiplicity is one (at least for all measure typed properties), and where a flat property structure is important for clients, the property could be represented as two properties in JSON, one for the numeric value and one for the unit. The property for the unit should have a suffix of "_uom" added to the property name. If the list of allowed units is known, these should be added as enum values. A dependency can be used to ensure that a unit is provided, if the numeric value is provided.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"type" : "object",
"properties" : {
"length" : {
"type" : "number"
},
"length_uom" : {
"type" : "string",
"enum" : [ "m", "ft" ]
}
},
"dependencies" : {
"length" : [ "length_uom" ]
}
}
1
2
3
4
{
"length" : 45.6,
"length_uom" : "m"
}
Note
|
In order to convert an application schema that has properties with a maximum multiplicity greater than one to an implementation schema where all properties have a maximum multiplicity of one, the ShapeChange Flattener transformation can be used - more specifically, rule-trf-prop-flatten-multiplicity. A new Flattener transformation rule has been implemented in UGAS-2020, rule-trf-prop-flatten-measure-typed-properties, which can be used to transform measure typed properties (essentially changing the type to Numeric and creating a "..uom" property with value type _CharacterString. The resulting model is closer to the flat representation. However, uom enums and property dependencies are not created. If it turns out that this is important, then future work can design and implement a solution for achieving the full encoding for a flat measure representation. |
7.3.2.2.2. Any
Since any value is a valid instance of the type Any, the type is mapped to JSON Schema (see Listing 35) so that all values - simple JSON types and objects - are valid.
1
2
3
4
5
6
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Any.json",
"title": "Any value",
"type": ["boolean", "number", "integer", "string", "object"]
}
The conversion of other property characteristics (multiplicity, voidable, inline or by reference encoding, uniqueness) of a property with value type Any should follow the same rules as described in Properties.
For example, an object with a property metadata : Any [0..*]
would be implemented as
metadata : Any [0..*]
1
2
3
4
5
6
7
8
9
10
11
12
{
"type" : "object",
"properties" : {
"metadata" : {
"type" : "array",
"items" : {
"$ref" : "http://www.opengis.net/tbd/Any.json"
},
"uniqueItems": true
}
}
}
The following values are all valid:
-
"metadata" : []
-
"metadata" : [ true ]
-
"metadata" : [ "abc", "def" ]
-
"metadata" : [ { "abc" : "def" } ]
-
"metadata" : [ { "abc" : [ 123, 456 ] } ]
7.3.2.2.3. Record
The basic type Record is implemented in JSON by a JSON object with one property per field.
Listing 37 shows a generic JSON schema for Record instances with no defined record type. The schema of a Record with a record type is specified by a more specific JSON schema, see Record Type.
1
2
3
4
5
6
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Record.json",
"title": "A record value",
"type": "object"
}
7.3.2.2.4. Record Type
RecordType is implemented in JSON as a JSON schema of type "object". The properties of the object are the fields. Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.example.com/MyRecordType.json",
"title": "My record value",
"type" : "object",
"properties" : {
"timestamp" : {
"type" : "string",
"format" : "date-time"
},
"temperature_Cel" : {
"type" : "number",
"minimum" : -273.15
}
}
}
Note
|
In this case "Cel" is used as the unit for degrees Celsius, using the symbol for this unit from [UCUM](https://ucum.org/ucum.html). |
7.3.3. Spatial Types
The Features Core Profile includes:
-
geometric primitives for dimensions 0d, 1d, 2d and 3d with linear (1d) or planar (2d) interpolation; and
-
geometric aggregates of these primitives.
Overview lists these types (for both ISO 19107:2003 and ISO 19107:2019) and documents the constraints on these types.
Type in ISO 19107:2003 | Interface in ISO 19107:2019 | NAS equivalent | JSON Schema implementation reference |
---|---|---|---|
GM_Point |
Point |
GeometryPoint |
|
GM_MultiPoint |
Collection |
MultiPointGeometry |
|
GM_Curve |
Line |
GeometryCurve |
|
GM_MultiCurve |
Collection |
MultiCurveGeometry |
|
GM_Surface |
Polygon |
GeometrySurface |
|
GM_MultiSurface |
Collection |
MultiSurfaceGeometry |
|
GM_Solid |
Solid |
GeometrySolidRep (abstract) |
|
GM_MultiSolid |
Collection |
MultiSolidGeometry (abstract) |
|
GM_Object |
Geometry |
GeometryObjectRepresentation (abstract) |
7.3.3.1. JSON Schema implementation
The JSON schemas in this Features Core Profile are specified so that point, line string and polygon geometries, including aggregates, continue to conform to GeoJSON.
In addition, polyhedra, including collections of polyhedra, are supported. A polyhedron is a solid that has closed polyhedral surfaces as exterior and interior boundaries.
Note
|
The term "polyhedron" is used to reflect that only solids with closed polyhedral surfaces as boundaries are supported, just like line strings are a subset of all curves and polygons are a subset of all surfaces. |
The JSON representations of the geometries included in the Features Core Profile extend the GeoJSON definitions with a property "crs" to specify the spatial coordinate reference system (CRS) of the geometry. The value of the "crs" property in the Features Core Profile is the URI of the CRS, consistent with "OGC API - Features - Part 2: Coordinate Reference Systems by Reference."
Note
|
Extensions could be defined to also support an array of CRS URIs (e.g., for a compound CRS) or a PROJJSON object as a value of the property. Clients should be prepared to receive and handle "crs"-values that are not a single URI. |
If the geometry is embedded in a context where a default CRS is stated, that default CRS is the CRS of the geometry, if no "crs" property is included in the geometry. If no default CRS is specified and no "crs" property is provided, the CRS is the GeoJSON default CRS, i.e., CRS84 or CRS84h depending on the coordinate dimension. This follows the current practice about the scope of a CRS declaration as it is, for example, used in GML 3.2.
For geometries with a coordinate dimension of one, a default CRS should be specified, too, but no decision was taken during the pilot. Two candidates are: [MSL height](http://www.opengis.net/def/crs/EPSG/0/5714) or [EGM2008 height](http://www.opengis.net/def/crs/EPSG/0/3855).
The coordinate dimension is restricted to one, two or three. That is, no "M" dimension is supported. Surfaces require a coordinate dimension of at least two, solids require coordinate dimension three.
While it is a key principle to conform to GeoJSON, where possible, it is equally important to avoid that geometries that do not conform to GeoJSON are mistaken by tools as GeoJSON.
For example, geometries with a coordinate dimension of one are not in scope of GeoJSON, i.e., such geometries do not conform to GeoJSON. Using a value of "Point" for "type" (as used in GeoJSON) for such instances would create interoperability issues. Clients would need to use the Content-Type header (if the file is received as an HTTP response) or other information (file extension or information provided by the user) to disambiguate a GeoJSON geometry from a Features Core Profile JSON geometry that does not meet the GeoJSON requirements. It seems safer to restrict the use of "Point" etc. to geometries that conform to GeoJSON, but require the use of a different value, e.g., "ogc:Point", for other cases. The schemas and examples in this section use an "ogc" prefix in cases where a geometry does not conform to GeoJSON.
The JSON schemas specified in this section include a property "bbox", which has been introduced since the GeoJSON geometries include the option to add a [bounding box in addition to the geometry](https://tools.ietf.org/html/rfc7946#section-5). However, it is unclear how often such a property is used in practice and it could also be discussed to drop the property from the schemas.
Note
|
There are a number of constraints that cannot be expressed in JSON Schema:
If an application required that the JSON Schemas for geometry types be restricted to either 2D or 3D, but not both, then 2D and 3D specific JSON Schemas could be developed. Such schemas would be able to express the two constraints. |
General pattern
Geometries are specified as nested arrays, where each array represents a geometry. The level of nesting for each geometry is shown in square brackets.
-
point [1]: A coordinate array with a value for each axis of the CRS. The number of elements (one, two, or three) depends on the CRS.
-
multi-point [2]: An array of point arrays. The order of the elements is not significant.
-
line string [2]: An array of point arrays with a minimum of 2 elements. The order reflects the sequence of the points along the line string.
-
multi-line-string [3]: An array of line string arrays. The order of the elements is not significant.
-
polygon [3]: An non-empty array of line string arrays. Each line string is a ring and must be closed (the first and the last point are identical). The first ring is the exterior boundary all other rings are holes.
-
multi-polygon [4]: An array of polygon arrays. The order of the elements is not significant.
-
polyhedron [5]: An non-empty array of multi-polygon arrays. Each multi-polygon is a shell and must be closed. The first shell is the exterior boundary all other shells are holes.
-
multi-polyhedron [6]: An array of polyhedron arrays. The order of the elements is not significant.
Point
A point is a coordinate array with a value for each axis of the CRS. The number of elements (one, two, or three) depends on the CRS.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Point.json",
"title": "A point geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Point",
"ogc:Point"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"minItems": 1,
"maxItems": 3,
"items": {
"type": "number"
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 2, "maxItems": 2 },
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
1
2
3
4
5
6
7
8
9
{
"type":"Point",
"crs":"http://www.opengis.net/def/crs/OGC/0/CRS84h",
"coordinates":[
36.0964929,
32.6020818,
436.46
]
}
1
2
3
4
5
6
7
{
"type":"ogc:Point",
"crs":"http://www.opengis.net/def/crs/EPSG/0/5714",
"coordinates":[
436.34
]
}
MultiPoint
A multi-point is an array of point arrays. The order of the points is not significant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/MultiPoint.json",
"title": "A multi-point geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiPoint",
"ogc:MultiPoint"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 1,
"maxItems": 3,
"items": {
"type": "number"
}
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 2, "maxItems": 2 },
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
LineString
A line string is an array of point arrays, with a minimum of 2 elements. The order reflects the sequence of the points along the line string.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/LineString.json",
"title": "A line string geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"LineString",
"ogc:LineString"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"minItems": 2,
"items": {
"type": "array",
"minItems": 1,
"maxItems": 3,
"items": {
"type": "number"
}
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 2, "maxItems": 2 },
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"type":"LineString",
"crs":"http://www.opengis.net/def/crs/OGC/0/CRS84h",
"coordinates":[
[
36.4251993,
32.7137029,
436.34
],
[
36.4270026,
32.7114543,
436.12
]
]
}
1
2
3
4
5
6
7
8
9
10
11
12
{
"type":"ogc:LineString",
"crs":"http://www.opengis.net/def/crs/EPSG/0/5714",
"coordinates":[
[
436.12
],
[
436.34
]
]
}
MultiLineString
A multi-line-string is an array of line string arrays. The order of the line strings is not significant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/MultiLineString.json",
"title": "A multi-line-string geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiLineString",
"ogc:MultiLineString"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 2,
"items": {
"type": "array",
"minItems": 1,
"maxItems": 3,
"items": {
"type": "number"
}
}
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 2, "maxItems": 2 },
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
Polygon
A polygon is an non-empty array of line string arrays. Each line string is a ring and must be closed (the first and the last point are identical). The first rings is the exterior boundary all other rings are holes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Polygon.json",
"title": "A polygon geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Polygon"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 3,
"items": {
"type": "number"
}
}
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
MultiPolygon
A multi-polygon is an array of polygon arrays. The order of the polygons is not significant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/MultiPolygon.json",
"title": "A multi-polygon geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiPolygon"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 3,
"items": {
"type": "number"
}
}
}
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
Polyhedron
A polyhedron is an non-empty array of multi-polygon arrays. Each multi-polygon array is a shell and must be closed. The first shell is the exterior boundary, all other shells are holes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Polyhedron.json",
"title": "A polyhedron geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Polyhedron"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": {
"type": "number"
}
}
}
}
}
},
"bbox": {
"type": "array",
"minItems": 6,
"maxItems": 6,
"items": {
"type": "number"
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{
"type":"Polyhedron",
"crs":"http://www.opengis.net/def/crs/OGC/0/CRS84h",
"coordinates": [
[
[
[
[ 36.1005693, 32.6345205, 436.3],
[ 36.1006509, 32.6345642, 436.3],
[ 36.1006133, 32.6346141, 436.3],
[ 36.1005316, 32.6345704, 436.3],
[ 36.1005693, 32.6345205, 436.3]
]
]
],
[
[
[
[ 36.1005693, 32.6345205, 439.8 ],
[ 36.1006509, 32.6345642, 439.8 ],
[ 36.1006133, 32.6346141, 439.8 ],
[ 36.1005316, 32.6345704, 439.8 ],
[ 36.1005693, 32.6345205, 439.8 ]
]
]
],
[
[
[
[ 36.1005693, 32.6345205, 436.3],
[ 36.1006509, 32.6345642, 436.3],
[ 36.1006509, 32.6345642, 439.8 ],
[ 36.1005693, 32.6345205, 439.8 ],
[ 36.1005693, 32.6345205, 436.3]
]
]
],
[
[
[
[ 36.1006509, 32.6345642, 436.3],
[ 36.1006133, 32.6346141, 436.3],
[ 36.1006133, 32.6346141, 439.8 ],
[ 36.1006509, 32.6345642, 439.8 ],
[ 36.1006509, 32.6345642, 436.3]
]
]
],
[
[
[
[ 36.1006133, 32.6346141, 436.3],
[ 36.1005316, 32.6345704, 436.3],
[ 36.1005316, 32.6345704, 439.8 ],
[ 36.1006133, 32.6346141, 439.8 ],
[ 36.1006133, 32.6346141, 436.3]
]
]
],
[
[
[
[ 36.1005316, 32.6345704, 436.3],
[ 36.1005693, 32.6345205, 436.3],
[ 36.1005693, 32.6345205, 439.8 ],
[ 36.1005316, 32.6345704, 439.8 ],
[ 36.1005316, 32.6345704, 436.3]
]
]
]
]
}
MultiPolyhedron
A multi-polyhedron is an array of polyhedron arrays. The order of the polyhedra is not significant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/MultiPolyhedron.json",
"title": "A multi-polyhedron geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"MultiPolyhedron"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 4,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": {
"type": "number"
}
}
}
}
}
}
},
"bbox": {
"type": "array",
"minItems": 6,
"maxItems": 6,
"items": {
"type": "number"
}
}
}
}
Geometry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Geometry.json",
"title": "A Features Core Profile geometry",
"type": "object",
"oneOf": [
{"$ref": "http://www.opengis.net/tbd/Point.json"},
{"$ref": "http://www.opengis.net/tbd/MultiPoint.json"},
{"$ref": "http://www.opengis.net/tbd/LineString.json"},
{"$ref": "http://www.opengis.net/tbd/MultiLineString.json"},
{"$ref": "http://www.opengis.net/tbd/Polygon.json"},
{"$ref": "http://www.opengis.net/tbd/MultiPolygon.json"},
{"$ref": "http://www.opengis.net/tbd/Polyhedron.json"},
{"$ref": "http://www.opengis.net/tbd/MultiPolyhedron.json"}
]
}
7.3.4. Temporal Types
On the conceptual level, Date and DateTime are data types for literal values in the Gregorian calendar. These are basic types and their mapping has already been specified in Table 7.
TM_Instant is a temporal 0d geometry, TM_Period a temporal 1d geometry. Both are in general not restricted to the Gregorian calendar, but the Features Core Profile is restricted to temporal information in the Gregorian calendar. The JSON representations of TM_Instant and TM_Period for the Features Core Profile are, therefore, based on literal values based on the representations of Date and DateTime.
In addition, special values are supported.
-
Unknown: Only supported for time intervals (unknown start or end). Represented as a blank/empty string (""). This is based on ISO 8601-2.
-
Open: Only supported for time intervals (open start or end). Represented as a double-dot (".."). This is based on ISO 8601-2.
-
Now: Supported for time instants and time intervals. Represented as "now". When processed, "now" should be resolved to the system date-time consistent with RFC 3339. Every subsequent use of the same temporal instant or interval in the same processing step (e.g., an API call) should use the same value.
Since the special values are not always needed, there are two JSON Schema variants, one restricted to date/time values according to RFC 3339 and one with the additional special values. See Table 9.
Type | JSON Schema implementation reference |
---|---|
TM_Instant |
|
TM_Period |
1
2
3
4
5
6
7
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/InstantRfc3339.json",
"title": "A temporal instant in the Gregorian calendar according to RFC 3339",
"type": "string",
"pattern": "^\\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):([0-5][0-9])))?)?)?$"
}
This pattern allows the following values:
-
year
-
year, and month
-
year, month, and day
-
year, month, day, timestamp (fractional seconds are optional), and time zone
Additional constraints:
-
the day must be valid for the month
-
the seconds must be valid according to the rules for leap seconds
Listing 54 adds the special value "now".
1
2
3
4
5
6
7
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/InstantGregorian.json",
"title": "A temporal instant in the Gregorian calendar according to RFC 3339 or 'now'",
"type": "string",
"pattern": "^\\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):([0-5][0-9])))?)?)?|now$"
}
1
2
3
4
5
6
7
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/SimpleIntervalRFC3339.json",
"title": "A temporal interval in the Gregorian calendar where start and end instant conform to RFC 3339",
"type": "string",
"pattern": "^\\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):([0-5][0-9])))?)?)?\\/\\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):([0-5][0-9])))?)?)?$"
}
Listing 56 adds the special value "now" for start/end dates that are now, ".." for open start/end dates and "" for unknown start/end dates.
1
2
3
4
5
6
7
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/SimpleIntervalGregorian.json",
"title": "A temporal interval in the Gregorian calendar with support for start or end dates that are open, unknown or now",
"type": "string",
"pattern": "^(\\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):([0-5][0-9])))?)?)?|(\\.\\.)?|now)\\/(\\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):([0-5][0-9])))?)?)?|(\\.\\.)?|now)$"
}
Some examples:
Instants |
|
|
the year 2020 |
|
July 2020 |
|
July 22, 2020 |
|
2:06pm on July 22, 2020 in the CEST time zone (for example) |
|
the current date/time |
Intervals |
|
|
the year 2020 as a date interval |
|
8am to 9am EDT (for example) on July 23, 2020 |
|
an interval starting on July 1, 2020; end is unknown |
|
an open interval starting on July 1, 2020 |
|
an interval starting on January 1, 2020 until now |
|
from 2000 until 2010 |
7.3.5. Features
This section specifies how the GeoJSON feature encoding can be extended to support the additional JSON schema capabilities of the Features Core Profile described above.
7.3.5.1. General remarks
By default, all properties are encoded in the "properties" object in the JSON feature object unless specified otherwise. See Nested Properties for more details.
7.3.5.2. AnyFeature
The JSON schema for the AnyFeature type from ISO 19109 in Listing 57 is based on the GeoJSON feature schema with the following changes based on the spatial types (see Spatial Types).
-
A "crs" property has been added with the same semantics.
-
The "bbox" property has been changed to express the constraint that the number of elements must be twice the coordinate dimension.
-
The "geometry" property also supports (multi-)polyhedron geometries.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Feature.json",
"title": "A feature",
"type": "object",
"required": [
"type",
"properties",
"geometry"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Feature",
"ogc:Feature"
]
},
"id" : {
"oneOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"properties": {
"oneOf": [
{
"type": "null"
},
{
"type": "object"
}
]
},
"crs": {
"type": "string",
"format": "uri"
},
"geometry": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "http://www.opengis.net/tbd/Point.json"
},
{
"$ref": "http://www.opengis.net/tbd/MultiPoint.json"
},
{
"$ref": "http://www.opengis.net/tbd/LineString.json"
},
{
"$ref": "http://www.opengis.net/tbd/MultiLineString.json"
},
{
"$ref": "http://www.opengis.net/tbd/Polygon.json"
},
{
"$ref": "http://www.opengis.net/tbd/MultiPolygon.json"
},
{
"$ref": "http://www.opengis.net/tbd/Polyhedron.json"
},
{
"$ref": "http://www.opengis.net/tbd/MultiPolyhedron.json"
}
]
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 2, "maxItems": 2 },
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
7.3.5.4. Spatial attributes
The General Feature Model in ISO 19109 supports multiple geometry properties per feature, while GeoJSON is restricted to a single spatial geometry.
If a feature type has a single geometry property, it is mapped to the top-level property "geometry" in the JSON feature object.
In case of multiple geometry properties in a feature type, one property (the default geometry) is mapped to the "geometry" property. The additional properties can be suppressed or included in the "properties" object like other feature properties. See also Default Geometry.
7.3.5.5. Temporal attributes
Temporal properties of the feature are encoded in the "properties" object.
7.3.5.6. Metadata or data quality attributes
Metadata or data quality properties are encoded in the "properties" object.
7.3.5.7. Association roles
If the value of a property is another feature / object, the UML-to-JSON-Schema encoding rule offers three options: always inline, always by-reference or either inline or by-reference.
The by-reference value may either be just a URI string or a link object, depending on the encoding preferences. The URI string is simpler to use for clients that prefer a simple structure, and would also lend itself better to a JSON to RDF conversion, but the link object has additional information (e.g., a title describing the link) that may be useful to clients.
The pilot has not specified, if all options should be supported in the JSON encoding of the Features Core Profile or if it should be more restrictive. Supporting all options leaves more flexibility, which in turn adds complexity to client implementations that have to be prepared for all options. Finding the sweet spot should be subject to testing in implementations and broader discussion. Note that there is a related discussion in the OGC API Records SWG in the context of querying the records (issue 28).
1
2
3
4
5
6
7
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/ByReference.json",
"title": "A reference encoded as a URI",
"type": "string",
"format": "uri"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/Link.json",
"title": "A reference encoded as a web link according to RFC 8288",
"type": "object",
"required": [
"href",
"rel"
],
"properties": {
"href": {
"type": "string",
"format": "uri"
},
"rel": {
"type": "string"
},
"type": {
"type": "string"
},
"hreflang": {
"type": "string"
},
"title": {
"type": "string"
},
"length": {
"type": "integer"
}
}
}
1
2
3
{
"$ref" : "{$id of the schema of the value type}"
}
1
2
3
4
5
6
7
8
9
10
11
12
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "Example of and association role value that is encoded inline or by reference (using a URI)",
"oneOf": [
{
"type": "string",
"format": "uri"
}, {
"$ref" : "{$id of the schema of the value type}"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "Example of and association role value that is encoded inline or by reference (using a link object)",
"oneOf": [
{
"$ref" : "http://www.opengis.net/tbd/Link.json"
}, {
"$ref" : "{$id of the schema of the value type}"
}
]
}
7.3.5.8. Feature collections
Feature collections are not specified in ISO 19109 and they are, therefore, not part of the Features Core Profile. However, for sharing feature data in JSON, feature collections are important and need to be included at least in the JSON representation of the Features Core Profile.
Like with the feature schema, the GeoJSON schema for a feature collection is used as the basis and extended / amended.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/FeatureCollection.json",
"title": "A feature collection",
"type": "object",
"required": [
"type",
"features"
],
"properties": {
"type": {
"type": "string",
"enum": [
"FeatureCollection",
"ogc:FeatureCollection"
]
},
"crs": {
"type": "string",
"format": "uri"
},
"type": {
"type": "array",
"items": {
"$ref" : "http://www.opengis.net/tbd/Feature.json"
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 2, "maxItems": 2 },
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 }
],
"items": {
"type": "number"
}
}
}
}
7.3.5.9. Example
The schema for a particular feature type, a subtype of AnyFeature, would then be encoded as a combination of the AnyFeature schema and the details for the specific feature type using "allOf". The example Listing 64 illustrates this and constrains the feature to have a solid geometry plus it defines four known properties.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.example.com/some/path/Building.json",
"title": "A building",
"allOf": [
{
"$ref": "http://www.opengis.net/tbd/Feature.json"
}, {
"type": "object",
"properties": {
"geometry": {
"$ref": "http://www.opengis.net/tbd/Polyhedron.json"
},
"properties": {
"type": "object",
"properties": {
"function" : {
"type" : "string",
"enum" : [ "residential", "public use", "commercial", "other" ]
},
"floors" : {
"type" : "integer"
},
"parcel" : {
"type": "string",
"format": "uri"
},
"lastUpdate" : {
"type" : "string",
"format" : "date-time"
}
}
}
}
}
]
}
7.4. Extensions
This section documents extensions of the Features Core Profile, which, if standardized, should be in separate conformance classes. These extensions can serve as starting points for the development of additional extensions.
7.4.1. Spatio-temporal geometries
The new edition of ISO 19111:2019 supports spatio-temporal coordinate referencing, which enables the use of, for example, the Point or Line types from ISO 19107:2019 with spatio-temporal coordinates (spatio-temporal points and trajectories).
In the JSON encoding, two CRSs could be specified (spatial and temporal) and coordinates could consist of numbers (spatial coordinates) or RFC 3339 values (temporal coordinates).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/PointST.json",
"title": "A spatio-temporal point geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"ogc:PointST"
]
},
"crs": {
"oneOf" : [ {
"type": "string",
"format": "uri"
}, {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
"type": "string",
"format": "uri"
}
} ]
},
"coordinates": {
"type": "array",
"minItems": 2,
"maxItems": 4,
"items": {
"oneOf": [
{
"type": "number"
}, {
"type": "string"
}
]
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 },
{ "minItems": 8, "maxItems": 8 }
],
"items": {
"oneOf": [
{
"type": "number"
}, {
"type": "string"
}
]
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"type" : "Feature",
"geometry" : {
"type" : "ogc:PointST",
"crs" : [ "http://www.opengis.net/def/crs/OGC/0/CRS84h", "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian" ],
"coordinates" : [ 6.9299617, 50.000008, 105.2, "2019-07-01T10:00:00Z" ]
},
"properties" : {
"observedProperty" : "temperature",
"result" : 22.3,
"result_uom" : "Cel"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "http://www.opengis.net/tbd/LineStringST.json",
"title": "A spatio-temporal line string geometry",
"type": "object",
"required": [
"type",
"coordinates"
],
"properties": {
"type": {
"type": "string",
"enum": [
"ogc:LineStringST"
]
},
"crs": {
"oneOf" : [ {
"type": "string",
"format": "uri"
}, {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
"type": "string",
"format": "uri"
}
} ]
},
"coordinates": {
"type": "array",
"items": {
"type": "array",
"minItems": 2,
"maxItems": 4,
"items": {
"oneOf": [
{
"type": "number"
}, {
"type": "string"
}
]
}
}
},
"bbox": {
"type": "array",
"oneOf": [
{ "minItems": 4, "maxItems": 4 },
{ "minItems": 6, "maxItems": 6 },
{ "minItems": 8, "maxItems": 8 }
],
"items": {
"oneOf": [
{
"type": "number"
}, {
"type": "string"
}
]
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"type" : "Feature",
"geometry" : {
"type" : "ogc:LineStringST",
"crs" : [ "http://www.opengis.net/def/crs/OGC/1.3/CRS84", "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian" ],
"coordinates" : [[ 6.9299617, 50.000008, "2019-07-01T10:07:00Z" ],
[ 6.9546373, 49.998403, "2019-07-01T10:08:00Z" ],
[ 6.9834923, 50.004252, "2019-07-01T10:09:00Z" ],
[ 7.0134923, 50.015566, "2019-07-01T10:10:00Z" ],
[ 7.0285356, 50.025566, "2019-07-01T10:11:00Z" ],
[ 7.0354923, 50.036248, "2019-07-01T10:12:00Z" ]]
},
"properties" : {
"maximumWindSpeed_kph" : "126.5"
}
}
Note that OGC has recently published a standard OGC Moving Features Encoding Extension - JSON (MF-JSON) that includes a GeoJSON extension for trajectories that follows a different approach. MF-JSON adds the time series as a property datetimes
in the properties
object with an array of the time steps in the time series. The geometry of the feature is a line string and the number of positions in the line string must match the number of time steps. The extension above intentionally follows a different approach to explore how a spatio-temporal geometry extension could look like.
7.4.2. Non-linear Geometries
Curves with non-linear curve segments are important for the NAS, in particular, arcs, circles, elliptic arcs and ellipses as defined in ISO 19107 (old and new edition). Probably the best approach would be to define a new geometry type for each new curve type. For example, for (circular) arcs this could be defined using three positions on the arc (start, intermediate, and end position).
1
2
3
4
5
6
7
8
9
10
{
"type" : "Feature",
"geometry" : {
"type" : "ogc:Arc",
"coordinates" : [[ 7.0134923, 50.001248 ], [ 7.0234923, 50.021248 ], [ 7.0354923, 50.033248 ]]
},
"properties" : {
"attribute" : "value"
}
}
Similar definitions could be specified for other curve types using the CurveData data type from ISO 19107:2019 and its subtypes (the CurveData types "contain copies of the attributes needed for every Curve construction").
This would also allow to define a general curve type that consists of the connected sequence of curves. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"type" : "Feature",
"geometry" : {
"type" : "ogc:Curve",
"crs" : "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"segments" : [ {
"type" : "LineString",
"coordinates" : [[ 6.9299617, 50.000008 ], [ 7.0134923, 50.000008 ]]
}, {
"type" : "ogc:Arc",
"coordinates" : [[ 7.0134923, 50.000008 ], [ 7.0294923, 50.010008 ], [ 7.0134923, 50.020008 ]]
}, {
"type" : "LineString",
"coordinates" : [[ 7.0134923, 50.020008 ], [ 6.9299617, 50.020008 ]]
}, {
"type" : "ogc:Arc",
"coordinates" : [[ 6.9299617, 50.020008 ], [ 6.9139617, 50.010008 ], [ 6.9299617, 50.000008 ]]
} ]
},
"properties" : {
"altitude_ft" : "12000"
}
}
7.4.3. Temporal geometries in another temporal coordinate reference system
In the Features Core Profile, all time instants or time intervals are in the (proleptic) Gregorian calendar, which supports a JSON representation as a literal value using the ISO 8601 encoding. To support other temporal coordinate reference systems, an object representation as a (temporal) geometry is required. The general pattern for (spatio-temporal) geometry objects can be used.
There are two options. The first is to simply reuse the spatial geometry types, just with only a temporal CRS. For example:
1
2
3
4
5
{
"type" : "ogc:Point",
"crs" : "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian",
"coordinates" : [ "2019-07-01T10:34:00Z" ]
}
The next example is a time interval in the POSIX system used in UNIX (seconds since epoch). In this case, the interval is "2017-01-01T00:00:15Z/2017-01-01T07:46:39Z".
1
2
3
4
5
{
"type" : "ogc:LineString",
"crs" : "http://www.example.com/def/crs/posix",
"coordinates" : [ [ 1483228815 ], [ 1483299999 ] ]
}
Alternatively, a more specific encoding with explicit types for time instants and intervals could be used:
1
2
3
4
5
{
"type" : "ogc:Instant",
"crs" : "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian",
"coordinates" : [ "2019-07-01T10:34:00Z" ]
}
1
2
3
4
5
{
"type" : "ogc:Interval",
"crs" : "http://www.example.com/def/crs/posix",
"coordinates" : [ 1483228815, 1483299999 ]
}
Whether explicit types would be beneficial requires analysis and testing. One benefit could be easier mapping to RDF in JSON-LD contexts.
8. Using SHACL for Validation of Linked Data
8.1. Overview
One of the tasks in the OGC UGAS-2020 Pilot project was to analyze the potential use of the Shapes Constraint Language (SHACL) to validate linked data.
Previous work related to this topic by the OGC Interoperability Program includes, but is not limited to the following.
-
The OGC Testbed-12 ShapeChange Engineering Report documents rules for converting a UML-based application schema to OWL ontologies.
-
The OGC Testbed-14: Application Schema-based Ontology Development Engineering Report complements the work performed in OGC Testbed-12, in that it defines additional rules for converting application schema elements to OWL ontologies. These rules cover the topics of property enrichment and property generalization. Furthermore, an analysis of how OCL constraints can be translated to OWL expressions was conducted. That analysis resulted in detailed conversion instructions for most OCL language constructs that were being investigated, but also revealed that some of these language constructs cannot be translated to OWL.
-
The OGC Testbed-14: Characterization of RDF Application Profiles for Simple Linked Data Application and Complex Analytic Applications Engineering Report worked on defining a concept of application profiles for ontologies, using OWL and SHACL.
All of these reports identified that future work should include an analysis of how UML-based application schemas, including OCL constraints defined in such schemas, can be converted to SHACL, as a means to perform validation of linked data. These work items have been addressed by the UGAS-2020 Pilot. This chapter documents the results of the according analysis.
The remaining sections of this chapter are structured as follows: The Validation of Linked Data section explains what validation of Linked Data actually means, when considering ontologies and SHACL as validation technologies. The Shapes Constraint Language (SHACL) section gives an introduction to SHACL, explaining key concepts and SHACL language constructs. The SHACL Conversion Rules section defines rules for converting a UML-based application schema, including OCL constraints, to SHACL validation constructs. Finally, a Summary of the results documented in this chapter is provided.
Note
|
Within this chapter, the following namespace prefix bindings are used:
|
8.2. Validation of Linked Data
In order to understand how SHACL can be used for validation of Linked Data, it is crucial to achieve a common understanding of what Linked Data and validation of such data actually means.
The W3C provides a useful introduction to Linked Data on https://www.w3.org/standards/semanticweb/data. That page explains the term Linked Data in more detail, and how it relates to Semantic Web, Vocabularies, Queries, Inference, and applications. Quoting directly from that page:
What is Linked Data?
The Semantic Web is a Web of Data — of dates and titles and part numbers and chemical properties and any other data one might conceive of. The collection of Semantic Web technologies (RDF, OWL, SKOS, SPARQL, etc.) provides an environment where applications can query that data, draw inferences using vocabularies, etc.
However, to make the Web of Data a reality, it is important to have the huge amount of data on the Web available in a standard format, reachable and manageable by Semantic Web tools. Furthermore, not only does the Semantic Web need access to data, but relationships among data should be made available, too, to create a Web of Data (as opposed to a sheer collection of datasets). This collection of interrelated datasets on the Web can also be referred to as Linked Data.
To achieve and create Linked Data, technologies should be available for a common format (RDF), to make either conversion or on-the-fly access to existing databases (relational, XML, HTML, etc). It is also important to be able to setup query endpoints to access that data more conveniently. W3C provides a palette of technologies (RDF, GRDDL, POWDER, RDFa, the upcoming R2RML, RIF, SPARQL) to get access to the data.
What is Linked Data Used For?
Linked Data lies at the heart of what Semantic Web is all about: large scale integration of, and reasoning on, data on the Web. […]
A more terse definition of Linked Data is given on the W3C Semantic Web Wiki:
Linked Data is the data format that supports the Semantic Web. The basic rules for Linked Data are defined as:
Use Uniform Resource Identifiers (URIs) to identify things;
Use HTTP URIs so that these things can be referred to and looked up ("dereferenced") by people and user agents;
Provide useful information about the thing when its URI is dereferenced, using standard formats such as RDF/XML; and
Include links to other, related URIs in the exposed data to improve discovery of other related information on the Web.
For the purpose of this ER, the primary format for encoding linked data is the Resource Description Framework (RDF).
Note
|
For an introduction to RDF, read the RDF 1.1 Primer, which has links to the normative W3C specifications. |
Another format for encoding linked data is JSON-LD. JSON-LD is a concrete RDF syntax, meaning that most JSON-LD documents can be interpreted as RDF.
Note
|
The JSON-LD extensions to the RDF data model are documented in the chapter Relationship to RDF of the JSON-LD 1.1 specification. |
Using so-called JSON-LD context documents, JSON data can be interpreted as JSON-LD, and thus typically also as RDF.
Note
|
OGC Testbed-14 conducted an analysis on how the semantics of JSON data can be defined using JSON-LD. More specifically, it was investigated if and how GeoJSON data could be transformed to NEO RDF data, using JSON-LD context documents. The results of that analysis are documented in the OGC Testbed-14: Application Schemas and JSON Technologies Engineering Report. |
For the purpose of validating linked data, RDF data - where resources are identified by HTTP URIs - can be regarded as linked data. The RDF data may have been created in a number of ways. For example, it could have been created by transforming JSON data to RDF using JSON-LD context documents. Another example is that a web service provides RDF data from some data store, such as a relational database, or even another web service.
Validation of linked data can be done in two different ways.
-
Checking the logical consistency of the data, based upon a set of vocabularies that are used in the linked data. Formats to define such vocabularies are, for example, RDF Schema (RDFS) and the Web Ontology Language (OWL). These vocabularies are typically used to infer new information. A so-called reasoner is used to perform the according inferencing. Such a reasoner will also detect if the given RDF data is inconsistent to some vocabulary definition(s). In that case, inferences would not be produced. However, that the RDF data is inconsistent is a useful result. RDF data that is known to be inconsistent against its vocabularies can also be interpreted as being invalid.
-
Checking that RDF data satisfies a set of structural constraints. This is where SHACL comes into play.
The following example shows how validation of linked data can be performed using OWL and SHACL. It also highlights a number of Semantic Web concepts, such as open-world assumption (OWA), closed-world assumption (CWA), and inferencing.
Consider the following RDF data, written in the Turtle syntax.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<http://example.org/shacl/schema>
a owl:Ontology .
exschema:Building
a owl:Class ;
rdfs:subClassOf [
a owl:Restriction ;
owl:cardinality "1"^^xsd:nonNegativeInteger ;
owl:onProperty exschema:numberOfStorys ;
] .
exschema:numberOfStorys
a owl:DatatypeProperty ;
rdfs:domain exschema:Building ;
rdfs:range xsd:nonNegativeInteger .
The data shows an OWL ontology that defines a class exschema:Building
and a property exschema:numberOfStorys
. OWL and RDFS language constructs are used to define:
-
that a
exschema:Building
has exactly one value for propertyexschema:numberOfStorys
; and -
that the property
exschema:numberOfStorys
is used by resources of typeexschema:Building
and generally has a non-negative integer value.
Given the following RDF data:
1
2
3
4
5
6
7
ex:A exschema:numberOfStorys 0 .
ex:B a exschema:Building .
ex:C
a exschema:Building ;
exschema:numberOfStorys -1 .
An OWL reasoner will conclude that the data is inconsistent, because resource ex:C
is defined to be of type exschema:Building
but it has a negative integer value for property exschema:numberOfStorys
.
If we correct ex:C
and change the data as follows:
1
2
3
4
5
6
7
8
ex:A
exschema:numberOfStorys 0 .
ex:B a exschema:Building .
ex:C
a exschema:Building ;
exschema:numberOfStorys 2 .
And let the reasoner run over the updated data, then no inconsistency is reported. This may be surprising, because ex:B
is declared to be a exschema:Building
, but it has no exschema:numberOfStorys
. The explanation for this behavior is that an OWL application works under the so-called open-world assumption (OWA), where facts not declared in the data are simply assumed to be unknown at present. That is different to an application with so-called closed-world assumption (CWA) - examples being SQL databases - where the available data is assumed to be complete, and anything not contained in the data is false. ex:B
is not marked as inconsistent by the reasoner because it could be the case that the exschema:numberOfStorys
is simply not yet known rather than being erroneously missing. In order to ensure that ex:B
has a value for the number of storys, SHACL can be used.
First, however, another important feature of OWL applications should be discussed, and that is inferencing. An OWL reasoner can not only detect inconsistencies in the data. As mentioned before, it can also produce new facts, based upon the axioms and expressions defined in the vocabularies, and given some RDF data.
Note
|
The OWL 2 Web Ontology Language Primer, chapter Modeling Knowledge: Basic Notions, explains axioms and expressions in the context of OWL. |
In the example, one of the facts produced by inferencing is that the resource ex:A
also is a exschema:Building
. That is because the ontology defines that an instance of exschema:Building
is any resource that has exactly one (non-negative integer) value for exschema:numberOfStorys
- which is the case for ex:A
. RDFS and OWL are well suited for use cases where resources need to be classified. Healthcare is one application domain: a classification tool could help diagnose a disease based upon observed symptons, and given an OWL ontology that defines diseases with certain values for such symptoms. In much the same way, a classification tool could generate geospatial intelligence.
Note
|
Advanced features of SHACL, more specificall SHACL Rules, also support generating new facts. However, that feature of SHACL is not discussed further in this ER. |
Coming back to the example, how can the data be checked to ensure that all buildings have a meaningful value for the property exschema:numberOfStorys
? That is where SHACL comes into play. Consider the following RDF data:
1
2
3
4
5
6
7
8
9
10
exshacl:BuildingShape
a sh:NodeShape ;
sh:property [
sh:path exschema:numberOfStorys ;
sh:datatype xsd:integer ;
sh:minCount 1 ;
sh:maxCount 1 ;
sh:minInclusive 1 ;
] ;
sh:targetClass exschema:Building .
A SHACL shape for all resources that are of type exschema:Building
is defined, with constraints on property exschema:numberOfStorys
to ensure that each such resource has exactly one integer value for the property, and that that value is greater than or equal to 1.
Note
|
In the definition of property exschema:numberOfStorys , the range has been set to xsd:nonNegativeInteger on purpose, to demonstrate validation with SHACL. If the range had been defined as xsd:positiveInteger, a meaningful value would already have been achieved, because xsd:positiveInteger excludes 0, whereas xsd:nonNegativeInteger includes 0.
|
When a SHACL processor evaluates the shape against the corrected RDF data, ex:B
will be marked as invalid - because it is declared to be of type exschema:Building
but does not have a value for property exschema:numberOfStorys
, and SHACL does not operate under the open-world assumption.
The reason why ex:A
is not flagged as being invalid is that the RDF data does not explicitly declare ex:A
to be of type exschema:Building