JSON Schema
(since v2.10.0)
Overview
This target derives a JSON Schema representation from an application schema in UML.
NOTE: A number of configuration options and extensions have been implemented. They are documented in detail in the OGC UGAS-2020 Engineering Report. The report also documents which model transformations may need to be applied before executing this target, for example to transform association classes. Therefore, if you are looking for a complete introduction of the conversion from UML to JSON Schema, read the according chapter in the OGC Engineering Report first. This page provides a quick reference of the available conversion rules, parameters, and configuration elements.
Configuration
Class
The class for the Target implementation is de.interactive_instruments.ShapeChange.Target.JSON.JsonSchemaTarget.
Conversion Rules
The behavior for processing a model is primarily controlled through conversion rules. In addition, parameters and other configuration elements (like map entries) influence the way a schema is processed. An encoding rule represents a specific set of conversion rules.
An encoding rule is defined by an <EncodingRule> element.
Example:
<EncodingRule name="myGeoJson" extends="defaultGeoJson">
<rule name="rule-json-cls-basictype"/>
<rule name="rule-json-cls-codelist-uri-format"/>
<rule name="rule-json-cls-name-as-entityType"/>
<rule name="rule-json-cls-union-propertyCount"/>
<rule name="rule-json-cls-valueTypeOptions"/>
</EncodingRule>
The name attribute of the <EncodingRule> element defines the identifier of the encoding rule to be used in the defaultEncodingRule parameter.
NOTE: The encoding rules ‘defaultGeoJson’ and ‘defaultPlainJson’ are pre-configured in ShapeChange. They can thus be used as-is, without the need to explicitly define them in the configuration. They can also be extended as required (see the example).
The optional extends attribute of the <EncodingRule> element includes all rules from the referenced encoding rule in this encoding rule, too.
Each <rule> references either a conversion rule or – possibly in the future – a requirement or recommendation to be tested before the conversion process.
This target supports the rules defined in the following subsections.
rule-json-all-notEncoded
This conversion rule suppresses the conversion to JSON Schema of any model elements (more specifically: application schemas, classes, and properties) for which the “jsonEncodingRule” tag is set to “notEncoded”.
NOTE: The encoding rule “notEncoded” is defined in the standard rules, which can be included in the target configuration via:
<xi:include href=”https://shapechange.net/resources/config/StandardRules.xml” />
rule-json-cls-basictype
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.
NOTE: Uses of the stereotype <<BasicType>> with application schema classes are ignored by this conversion rule.
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. The following table 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 (inclusive) |
rangeMinimum | number, integer |
maximum (inclusive) |
rangeMaximum | number, integer |
rule-json-cls-codelist-link
This rule results in the conversion of a code list as a reference to the JSON Schema defining a link object. That reference must explicitly be configured using the target parameter linkObjectUri.
rule-json-cls-codelist-uri-format
With this rule, all code lists are 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).
rule-json-cls-defaultGeometry-multipleGeometryProperties
This conversion rule is typically used in case that a) a GeoJSON compliant encoding shall be created, and b) for application schemas with classes that 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.
rule-json-cls-defaultGeometry-singleGeometryProperty
This conversion rule is typically used in case that a) a GeoJSON compliant encoding shall be created, and b) 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-identifierForTypeWithIdentity
With rule-json-cls-identifierForTypeWithIdentity, an identifier JSON member will be added to the JSON object that represents a type with identity (feature type or object type). 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 optional or required.
rule-json-cls-identifierStereotype
This conversion rule assumes that all types with identity (feature type or object type) have an attribute with stereotype <<identifier>> (directly, or inherited from a supertype). That attribute is used to encode the identifier. The rule is typically used in conjunction with rule-json-cls-ignoreIdentifier, in order to detect identifier properties and not encode them (e.g. because a JSON Schema that applies to all types with identity already defines an identifier member).
NOTE: If 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 (feature type or object type) 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 rule-json-cls-virtualGeneralization). 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.
rule-json-cls-name-as-anchor
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.
rule-json-cls-name-as-entityType
The rule adds another JSON member to the JSON object which represents the class (a feature, object, or data type) that is being converted. The name of the JSON member can be configured using the target parameter entityTypeName. 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.
An example for the benefit of encoding the type name in JSON objects is given 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.
rule-json-cls-name-as-entityType-union
If this rule is enabled together with rule-json-cls-name-as-entityType, then the latter also applies to unions.
NOTE: rule-json-cls-name-as-entityType-union has been implemented because with rule-json-cls-union-propertyCount unions are converted to JSON objects. 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.
rule-json-cls-nestedProperties
By default, the properties of a type with identity (feature type or object 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.
rule-json-cls-union-propertyCount
With this rule, a <<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.
rule-json-cls-union-typeDiscriminator
With this rule, a <<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, 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 format, and
- one “type” per simple type with specific format.
rule-json-cls-valueTypeOptions
This rule looks for tagged value valueTypeOptions on a class (that is not a basic type, enumeration, or code list). If the tag exists and has a value, it defines which types are allowed as value type for a given UML property of the class. 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 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.
NOTE: Value type options can be parsed from OCL constraints using transformation rule-trf-cls-constraints-valueTypeRestrictionToTV-exclusion of the Constraint Converter.
rule-json-cls-virtualGeneralization
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: 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 being 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”).
rule-json-prop-derivedAsReadOnly
With this rule, a UML property marked as derived will be encoded with "readOnly": true
.
rule-json-prop-initialValueAsDefault
With this rule, 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.
rule-json-prop-readOnly
With this rule, the JSON Schema definition of a UML property that is read only or fixed will include the “readOnly” annotation with JSON value true.
rule-json-prop-voidable
With this rule, 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.
Rule execution priority and dependencies
Some of the conversion rules supported by this target address the same conversion aspects. When conflicting conversion rules are included in the encoding rule, ShapeChange usually only executes one of them. This section documents the execution priorities and dependencies of rules that address the same conversion aspects.
Code lists
The default behavior for encoding code lists is overridden whenever either rule-json-cls-codelist-link or rule-json-cls-codelist-uri-format is in the encoding rule.
These conversion rules are executed with the following priority:
Identifier
With rule-json-cls-identifierForTypeWithIdentity, an identifier member can be added to the JSON Schema representation of a type with identity (feature type or object type). That rule will be ignored if rule-json-cls-ignoreIdentifier also applies to the type with identity.
Union
The rules for converting unions are executed with the following priority:
Parameters
This target supports the parameters defined in the following subsections.
baseJsonSchemaDefinitionForDataTypes
Required / Optional: optional
Type: URI
Default Value: none
Explanation: Reference to the JSON Schema definition which shall be added to a data type in order to represent an additional generalization relationship under rule-json-cls-virtualGeneralization.
Applies to Rule(s): rule-json-cls-virtualGeneralization
baseJsonSchemaDefinitionForFeatureTypes
Required / Optional: optional
Type: URI
Default Value: none
Explanation: Reference to the JSON Schema definition which shall be added to a feature type in order to represent an additional generalization relationship under rule-json-cls-virtualGeneralization.
Applies to Rule(s): rule-json-cls-virtualGeneralization
baseJsonSchemaDefinitionForObjectTypes
Required / Optional: optional
Type: URI
Default Value: none
Explanation: Reference to the JSON Schema definition which shall be added to an object type in order to represent an additional generalization relationship under rule-json-cls-virtualGeneralization.
Applies to Rule(s): rule-json-cls-virtualGeneralization
byReferenceJsonSchemaDefinition
Required / Optional: optional
Type: URI
Default Value: none
Explanation: References a JSON Schema definition which shall be used to encode the value of a UML property “by reference”, i.e. somehow link to the actual value. That is relevant for cases in which tag inlineOrByReference of the UML property (taking into account target parameter inlineOrByReferenceDefault) has value byReference or inlineOrByReference. By setting this parameter, the default encoding for the “by reference” case – which is “type”: “string”, “format”: “uri” – can be overridden.
Applies to Rule(s): none – default behavior
defaultEncodingRule
Required / Optional: optional
Type: String
Default Value: *
Explanation: The identifier of the default encoding rule governing the conversion to JSON Schema. To use a custom encoding rule defined in the configuration, simply provide the name of the custom encoding rule via this parameter.
Applies to Rule(s): none – default behavior
entityTypeName
Required / Optional: optional
Type: String
Default Value: “entityType”
Explanation: The name of the JSON member to be added to a JSON object in order to encode the type represented by that object.
Applies to Rule(s): rule-json-cls-name-as-entityType
inlineOrByReferenceDefault
Required / Optional: optional
Type: Enumeration, one of “inline”, “byReference”, “inlineOrByReference”
Default Value: “byReference”
Explanation: Defines the default value for tag inlineOrByReference of a UML property, in case that tag is undefined or has an empty value for the property.
Applies to Rule(s): none – default behavior
jsonBaseUri
Required / Optional: optional
Type: URI
Default Value: http://example.org/FIXME
Explanation: The base URI, used to construct the value of the “$id” members of resulting JSON Schemas.
Note: If the tagged value jsonBaseUri of an application schema has a non empty value, then that value will be used as base URI for all JSON Schemas produced for the content of that application schema.
Applies to Rule(s): none – default behavior
jsonSchemaVersion
Required / Optional: optional
Type: Enumeration, one of “2019-09”, “draft-07”, “OpenApi30”
Default Value: “2019-09”
Explanation: Specifies the version of the resulting JSON Schemas.
Applies to Rule(s): none – default behavior
linkObjectUri
Required / Optional: optional
Type: URL
Default Value: none
Explanation: Reference to the JSON Schema of the “Link” object.
Applies to Rule(s): rule-json-cls-codelist-link
objectIdentifierName
Required / Optional: optional
Type: String
Default Value: “id”
Explanation: Name of the JSON member to be added to a JSON object that represents the type with identity.
Applies to Rule(s): rule-json-cls-identifierForTypeWithIdentity
objectIdentifierRequired
Required / Optional: optional
Type: Boolean
Default Value: false
Explanation: “false”, if the new object identifier member shall not be required, else “true”
Applies to Rule(s): rule-json-cls-identifierForTypeWithIdentity
objectIdentifierType
Required / Optional: optional
Type: String – one of “string”, “number”, or a (comma-separated) combination thereof
Default Value: “string”
Explanation: Value type of the JSON member to be added to a JSON object that represents the type with identity.
Applies to Rule(s): rule-json-cls-identifierForTypeWithIdentity
outputDirectory
Required / Optional: optional
Type: String
Default Value: <the current run directory>
Explanation: The path to which the JSON Schema file(s) will be written.
Applies to Rule(s): none – this is a common target parameter
prettyPrint
Type: Boolean
Default Value: true
Explanation: True if the resulting json schemas shall be pretty printed, else false.
Applies to Rule(s): none – default behavior
sortedOutput
Type: String
Default Value: “false”
Explanation:
- If “false”, the types in a schema will be processed in random order.
- If “true”, the types will be processed alphabetically.
- If “taggedValue=<tag>”, the types will be processed in the order of the values of the tagged value with name “<tag>”.
Applies to Rule(s): none – this is a common target parameter
writeMapEntries
Required / Optional: optional
Type: Boolean
Default Value: false
Explanation: If set to “true”, a map entry file will be written for each processed schema, containing a map entry for each encoded type from that schema.
Applies to Rule(s): none – this is a common target parameter
Map Entries
<mapEntries> contain individual <MapEntry> elements, which for this target contain information for mapping specific types (classes) from the UML model to either JSON Schema simple types, or using references to specific JSON Schema definitions.
Examples:
<mapEntries>
<MapEntry type="CharacterString" rule="*" targetType="string" param=""/>
<MapEntry type="URI" rule="*" targetType="string" param="keywords{format=uri}"/>
<MapEntry type="Boolean" rule="*" targetType="boolean" param=""/>
<MapEntry type="Integer" rule="*" targetType="integer" param=""/>
<MapEntry type="Real" rule="*" targetType="number" param=""/>
<MapEntry type="Measure" rule="*" targetType="number" param=""/>
<MapEntry type="DateTime" rule="*" targetType="string" param="keywords{format=date-time}"/>
<MapEntry type="GM_Point" rule="*" targetType="https://geojson.org/schema/Point.json" param="geometry"/>
</mapEntries>
A <MapEntry> element contains the attributes described in the following sections.
NOTE: StandardMapEntries_JSON.xml defines standard mappings for a number of types of the ISO Harmonized Model. This file can be included in ShapeChange configuration files (via XInclude – see the configuration example). Additional XInclude files, or individual <MapEntry> elements added to the <mapEntries> section of the configuration file, may be used to customize the map entries to support additional pre-defined conceptual UML classes.
type
Required / Optional: Required
Explanation: The unqualified UML type/class name to be mapped. Should be unique within the model (if it is not unique, this can lead to unexpected results).
rule
Required / Optional: Required
Explanation: The encoding rule to which this mapping applies. May be “*” to indicate that the mapping applies to all encoding rules.
targetType
Required / Optional: Required
Explanation: Name of a simple JSON Schema type (boolean, number, integer, or string), or a reference to a particular JSON Schema, typically expressed as a URL.
param
Required / Optional: Optional
Explanation: Defines one or more parameters for the mapping. If no parameter is provided (leaving the ‘param’ attribute empty) then the map entry contains a straightforward mapping.
Each parameter has a name. A list of parameters is separated by commas. Each parameter can also have characteristics defined for it, providing even further information for the conversion. Characteristics for a parameter are provided within curly braces. A characteristic usually is provided by a key-value pair, with the key being the identification of the characteristic.
Examples:
- geometry
- keywords{format=date}
Supported parameters, their interpretation as well as characteristics are described in the following sections.
Parameter: keywords
Explanation: Indicates that the simple JSON type (boolean, number, integer, string) that is the target of the map entry has one or more restrictions defined by JSON Schema keywords. The following keywords are supported – they also represent the characteristics of the parameter:
- for any simple JSON type: keyword format
- for JSON 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 (instead of pattern).
- for JSON types integer and number: keywords enum, const, multipleOf, maximum, minimum, exclusiveMaximum, exclusiveMinimum
Multiple keywords may be specified as a semicolon-delimited list, e.g.: “keywords{minimum=0;maximum=3}”.
Parameter: encodingInfos
Explanation: Provides additional information about the JSON encoding of the type, which is relevant for creating a JSON encoding that uses that type.
Characteristics:
- entityTypeMemberPath: The path to the JSON member that is used to encode the type name. Only used if the JSON encoding actually has such a member. Examples:
- plain JSON encoding: “@type”
- nested JSON encoding, e.g. GeoJSON encoding: “properties/@type”
Parameter: geometry
Explanation: Indicates that the map entry contains a mapping for a geometry type (specifically from ISO 19107). IMPORTANT: If geometry types are not identified via map entries containing this parameter then ShapeChange cannot determine geometry typed properties, which is relevant for default geometry encoding!
Characteristics: no specific characteristics are defined for this parameter
Parameter: ignoreForTypeFromSchemaSelectedForProcessing
Explanation: Set this parameter on map entries for types from external schemas, whose type name is the same as one of the types from the schemas selected for processing. For example, the SWE Common 2.0 schema defines a type called ‘Boolean’ – which is the same name as a type from ISO 19103 (‘Boolean’). If the parameter is set on a map entry for ‘Boolean’, then the type from the schema selected for processing is still encoded and used – otherwise it would not be encoded and instead mapped as defined by the map entry.
Characteristics: no specific characteristics are defined for this parameter
Configuration Example
<Target class="de.interactive_instruments.ShapeChange.Target.JSON.JsonSchemaTarget" mode="enabled">
<targetParameter name="outputDirectory" value="results/json_schema/2019-09"/>
<targetParameter name="sortedOutput" value="true"/>
<targetParameter name="jsonBaseUri" value="https://example.org/baseuri"/>
<targetParameter name="byReferenceJsonSchemaDefinition" value="https://example.org/jsonschema/byreference.json"/>
<targetParameter name="entityTypeName" value="@type"/>
<targetParameter name="defaultEncodingRule" value="myGeoJson"/>
<rules>
<EncodingRule name="myGeoJson" extends="defaultGeoJson">
<rule name="rule-json-cls-basictype"/>
<rule name="rule-json-cls-codelist-uri-format"/>
<rule name="rule-json-cls-name-as-entityType"/>
<rule name="rule-json-cls-union-propertyCount"/>
<rule name="rule-json-cls-valueTypeOptions"/>
</EncodingRule>
</rules>
<xi:include href="https://shapechange.net/resources/config/StandardMapEntries_JSON.xml"/>
</Target>