From a5860eb2501ec638b55cbbafed67c98318bccce7 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 10 May 2022 21:49:02 +0200 Subject: [PATCH] Doc: enhance PROJJSON specification --- docs/source/specifications/projjson.rst | 871 +++++++++++++++++++++++- 1 file changed, 839 insertions(+), 32 deletions(-) diff --git a/docs/source/specifications/projjson.rst b/docs/source/specifications/projjson.rst index c2280c0bcf..4f661461fc 100644 --- a/docs/source/specifications/projjson.rst +++ b/docs/source/specifications/projjson.rst @@ -4,35 +4,83 @@ PROJJSON ================================================================================ +Introduction +------------ + PROJJSON is a JSON encoding of -`WKT2:2019 / ISO-19162:2019 `_, +`WKT2:2019 / ISO-19162:2019: Geographic information - Well-known text representation of coordinate reference systems `_, which itself implements the model of -`OGC Topic 2: Referencing by coordinates `_. +`OGC Topic 2: Referencing by coordinates abstract specification / ISO-19111:2019 `_. Apart from the difference of encodings, the semantics is intended to be exactly -the same as WKT2:2019. +the same as WKT2:2019, and PROJJSON can be morphed losslessly from/into WKT2:2019. + +PROJJSON this is aimed at encoding definitions of coordinate reference systems (and their composing objects: datums, datum ensembles, coordinate systems, conversion) and coordinate operations. + +Normative references +-------------------- + +The PROJJSON specification requires prior knowledge of the following normative +specifications: -PROJJSON is available as input and output of PROJ since PROJ 6.2. +- `The JavaScript Object Notation (JSON) Data Interchange Format / IETF RFC 7159 `_ +- `WKT2:2019 / ISO-19162:2019: Geographic information - Well-known text representation of coordinate reference systems `_ -The current version is 0.4. +Definitions +----------- + +- JavaScript Object Notation (JSON), and the terms object, member, + name, value, array, number, true, false, and null, are to be + interpreted as defined in [RFC7159]. + +- integer: JSON number whose value has no fractional/exponent part. + +- All `term and definitions `_ + from WKT2:2019 apply. Schema ------ -A JSON schema of its grammar is available at +A JSON schema of PROJJSON grammar is available at https://proj.org/schemas/v0.4/projjson.schema.json -History -------- +This schema defines a minimum set of constraints that apply to well-formed PROJJSON. +Number of specific CRS and coordinate operation domain constraints are not expressed +as JSON schema constraints: unless otherwise stated, the constraints (optional/mandatory/conditional +character of information, restricted set of allowed values, etc.) defined +in the WKT2:2019 specification also apply, as supplement to the JSON schema constraints. + +History of the schema +--------------------- * v0.4: additional properties allowed in id object (version, authority_citation, uri) * v0.3: additional properties allowed in BoundCRS object (name, scope, area, bbox, usages, remarks, id, ids) * v0.2: addition of geoid_model in VerticalCRS object. * v0.1: initial version for PROJ 6.2 -Content -------- +Specification +------------- -The high level objects are: +A PROJJSON text is a JSON object which has, at a minimum, a required ``type`` member, +whose value is a string describing the nature of the encoded geodetic object. + +An optional ``$schema`` member may be present, with its value being a string with +a URL that points to the JSON schema that applies. + +Objects may be composed of sub-objects (e.g a GeographicCRS is made of a Datum or DatumEnsemble +and a coordinate system). The ``type`` member of the sub-objects can be omitted when +there is no ambiguity. For example, in the object which is the value of a ``coordinate_system`` +member, the ``type`` may be omitted. But for the value of the ``datum`` object of +a GeographicCRS the ``type`` should be specified, as it can be either a GeodeticReferenceFrame +or a DynamicGeodeticReferenceFrame. +More formally, if the JSON schema specifies alternative types for the value of a +member, using the oneOf construct, and that those alternative types have a ``type`` member, +then it should be specified. Otherwise it may be omitted. + +High level objects +++++++++++++++++++ + +The high level objects, that is the one that can be described at the first level +of a PROJJSON text, are the following potential values of the ``type`` member: * Coordinate Reference Systems (CRS): @@ -71,19 +119,123 @@ The high level objects are: - ``Datum`` - ``DatumEnsemble`` +.. _identifiers: + +Identifiers ++++++++++++ + +All above mentionned object can have an option ``id`` or ``ids`` member. + +The value of ``id`` is a JSON object with the following members: + +- ``authority``: (required) value of type string. e.g "EPSG", "OGC", "IGNF", etc. +- ``code``: (required) value of type string or integer. e.g 4326 or "CRS84" +- ``authority_citation``: (optional) value of type string that may be used to give + further details of the authority. +- ``uri``: (optional) value of type string that may be used to give reference + to an online resource. + +An object can sometimes be identified in different ways, in which case the ``ids`` +member can be used to specify a JSON array of objects with the same type of ``id``. + +Identifiers are allowed in top-level objects and inner objects. The WKT2:2019 +specification recommends that if an object has an identifier, its inner objects +should omit their identifiers, with the exceptions mentioned at +http://docs.opengeospatial.org/is/18-010r7/18-010r7.html#37. + +Object usages ++++++++++++++ + +CRS and coordinate operation objects are derived classes (in object modeling terminology) +of a "object usage" class. An object usage has the following optional members: + +- ``scope``: (optional) value of type string describing the purpose or purposes of + the object. e.g "Geodesy, topographic mapping and cadastre" +- ``area``: (optional) value of type string which describes a geographic area + over which a CRS or coordinate operation is applicable. e.g. "World" +- ``bbox``: (optional) value of type object, with 4 required members: + * ``east_longitude``: (required) number expressing the longitude in degrees in [-180,180] range of the eastern most part of the extent. + * ``west_longitude``: (required) number expressing the longitude in degrees in [-180,180] range of the western most part of the extent. For an extent crossing the anti-meridian, west_longitude is lower than east_longitude. + * ``south_latitude``: (required) number expressing the latitude in degrees in [-90,90] range of the southern most part of the extent. + * ``north_latitude``: (required) number expressing the latitude in degrees in [-90,90] range of the northern most part of the extent. + The coordinates are expressed in a unspecified datum, with the longitudes + relative to the international reference meridian. +- ``remarks``: (optional) value of type string with an informative text that does + not modify the definining parameters of the object. e.g "Use NTv2 file for better accuracy" +- ``id`` (mutually exclusive with ``ids``): (optional) Identifier of the object, as defined in :ref:`identifiers` +- ``ids`` (mutually exclusive with ``id``): (optional) Identifiers of the object, as defined in :ref:`identifiers` + +If several extents and scopes apply to an object, the ``scope``, ``area`` and ``bbox`` +members should not be used. Instead a ``usages`` member should be used, whose value +is an array of objects, each of them accepting ``scope`` and/or ``area`` and/or ``bbox`` +as members. While it is acceptable to use the ``usages`` construct for a single +usage, it is recommended to avoid it and rather use instead the +``scope``, ``area`` and ``bbox`` members. + +Units ++++++ + +A unit may be described either as: + +- an object with the following members: + * ``type``: (required) value of type string among the following enumeration: + ``LinearUnit``, ``AngularUnit``, ``ScaleUnit``, ``TimeUnit``, ``ParametricUnit``, ``Unit`` + * ``name``: (required) value of type string. + * ``conversion_factor``: (required in most cases, except in the temporal quantities of http://docs.opengeospatial.org/is/18-010r7/18-010r7.html#42) + Number that expresses a multiplicative factor to convert from the specified + unit to a reference unit, as specified in http://docs.opengeospatial.org/is/18-010r7/18-010r7.html#41 + * ``id`` or ``ids``: (optional, mutually exclusive) + +- a string among the following enumeration: ``metre``, ``degree``, ``unity`` + +The use of a string value, when applicable, is recommended for the brievity of +the object definition. + +Omitted units in measured parameters +++++++++++++++++++++++++++++++++++++ + +Most numeric parameters should generally be accompanied with the correspond unit. + +For example, for a projection parameter: + +.. code-block:: json + + { + "name": "False easting", + "value": 500000, + "unit": "metre" + } + +or: + +.. code-block:: json + + { + "name": "False easting", + "value": 700000, + "unit": { + "type": "LinearUnit", + "name": "foot", + "conversion_factor": 0.3048 + } + } + +For the following cases, the unit may be omitted if it is metre: +``semi_major_axis``, ``semi_minor_axis`` and ``radius`` members of an ellipsoid + +For the following cases, the unit may be omitted if it is degree: +``longitude`` of a prime meridian. + Examples -------- GeographicCRS +++++++++++++ -The following invocation - -:: - - projinfo EPSG:4326 -o PROJJSON -q +Using a datum member, implicit prime meridian +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -will output: +The EPSG:4326 / "WGS 84" geographic CRS can be expressed as .. code-block:: json @@ -130,17 +282,184 @@ will output: } } +Note the omission of a prime meridian member, which is conformant with the +WKT2:2019 conditionality rules, as the prime meridian of the WGS 84 datum is the +reference meridian / Greenwich. -ProjectedCRS -++++++++++++ +Using a datum member, explicit prime meridian +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For the EPSG:4806 / "Monte Mario (Rome)" geographic CRS, the prime meridian must +be specified: + +.. code-block:: json + + { + "$schema": "https://proj.org/schemas/v0.4/projjson.schema.json", + "type": "GeographicCRS", + "name": "Monte Mario (Rome)", + "datum": { + "type": "GeodeticReferenceFrame", + "name": "Monte Mario (Rome)", + "ellipsoid": { + "name": "International 1924", + "semi_major_axis": 6378388, + "inverse_flattening": 297 + }, + "prime_meridian": { + "name": "Rome", + "longitude": 12.4523333333333 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "scope": "Geodesy, onshore minerals management.", + "area": "Italy - onshore and offshore; San Marino, Vatican City State.", + "bbox": { + "south_latitude": 34.76, + "west_longitude": 5.93, + "north_latitude": 47.1, + "east_longitude": 18.99 + }, + "id": { + "authority": "EPSG", + "code": 4806 + } + } + +Using a datum ensemble member +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The WGS 84 geographic CRS may also be specified using a datum ensemble +representation of the WGS 84 datum: + +.. code-block:: json -The following invocation + { + "$schema": "https://proj.org/schemas/v0.4/projjson.schema.json", + "type": "GeographicCRS", + "name": "WGS 84", + "datum_ensemble": { + "name": "World Geodetic System 1984 ensemble", + "members": [ + { + "name": "World Geodetic System 1984 (Transit)", + "id": { + "authority": "EPSG", + "code": 1166 + } + }, + { + "name": "World Geodetic System 1984 (G730)", + "id": { + "authority": "EPSG", + "code": 1152 + } + }, + { + "name": "World Geodetic System 1984 (G873)", + "id": { + "authority": "EPSG", + "code": 1153 + } + }, + { + "name": "World Geodetic System 1984 (G1150)", + "id": { + "authority": "EPSG", + "code": 1154 + } + }, + { + "name": "World Geodetic System 1984 (G1674)", + "id": { + "authority": "EPSG", + "code": 1155 + } + }, + { + "name": "World Geodetic System 1984 (G1762)", + "id": { + "authority": "EPSG", + "code": 1156 + } + }, + { + "name": "World Geodetic System 1984 (G2139)", + "id": { + "authority": "EPSG", + "code": 1309 + } + } + ], + "ellipsoid": { + "name": "WGS 84", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257223563 + }, + "accuracy": "2.0", + "id": { + "authority": "EPSG", + "code": 6326 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "scope": "Horizontal component of 3D system.", + "area": "World.", + "bbox": { + "south_latitude": -90, + "west_longitude": -180, + "north_latitude": 90, + "east_longitude": 180 + }, + "id": { + "authority": "EPSG", + "code": 4326 + } + } + +The above is the output of the following invocation of the projinfo utility +of the PROJ software version 9.0.0 :: - projinfo EPSG:32631 -o PROJJSON -q + projinfo EPSG:4326 -o PROJJSON -q + +ProjectedCRS +++++++++++++ -will output: +The EPSG:32631 / "WGS 84 / UTM zone 31N" projected CRS can be expressed as .. code-block:: json @@ -196,8 +515,8 @@ will output: "value": 0, "unit": "degree", "id": { - "authority": "EPSG", - "code": 8801 + "authority": "EPSG", + "code": 8801 } }, { @@ -205,8 +524,8 @@ will output: "value": 3, "unit": "degree", "id": { - "authority": "EPSG", - "code": 8802 + "authority": "EPSG", + "code": 8802 } }, { @@ -214,8 +533,8 @@ will output: "value": 0.9996, "unit": "unity", "id": { - "authority": "EPSG", - "code": 8805 + "authority": "EPSG", + "code": 8805 } }, { @@ -223,8 +542,8 @@ will output: "value": 500000, "unit": "metre", "id": { - "authority": "EPSG", - "code": 8806 + "authority": "EPSG", + "code": 8806 } }, { @@ -232,8 +551,8 @@ will output: "value": 0, "unit": "metre", "id": { - "authority": "EPSG", - "code": 8807 + "authority": "EPSG", + "code": 8807 } } ] @@ -267,3 +586,491 @@ will output: "code": 32631 } } + +CompoundCRS ++++++++++++ + +The EPSG:9518 / "WGS 84 + EGM2008 height" compound CRS can be expressed as: + +.. code-block:: json + + { + "$schema": "https://proj.org/schemas/v0.4/projjson.schema.json", + "type": "CompoundCRS", + "name": "WGS 84 + EGM2008 height", + "components": [ + { + "type": "GeographicCRS", + "name": "WGS 84", + "datum_ensemble": { + "name": "World Geodetic System 1984 ensemble", + "members": [ + { + "name": "World Geodetic System 1984 (Transit)", + "id": { + "authority": "EPSG", + "code": 1166 + } + }, + { + "name": "World Geodetic System 1984 (G730)", + "id": { + "authority": "EPSG", + "code": 1152 + } + }, + { + "name": "World Geodetic System 1984 (G873)", + "id": { + "authority": "EPSG", + "code": 1153 + } + }, + { + "name": "World Geodetic System 1984 (G1150)", + "id": { + "authority": "EPSG", + "code": 1154 + } + }, + { + "name": "World Geodetic System 1984 (G1674)", + "id": { + "authority": "EPSG", + "code": 1155 + } + }, + { + "name": "World Geodetic System 1984 (G1762)", + "id": { + "authority": "EPSG", + "code": 1156 + } + }, + { + "name": "World Geodetic System 1984 (G2139)", + "id": { + "authority": "EPSG", + "code": 1309 + } + } + ], + "ellipsoid": { + "name": "WGS 84", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257223563 + }, + "accuracy": "2.0", + "id": { + "authority": "EPSG", + "code": 6326 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + } + }, + { + "type": "VerticalCRS", + "name": "EGM2008 height", + "datum": { + "type": "VerticalReferenceFrame", + "name": "EGM2008 geoid" + }, + "coordinate_system": { + "subtype": "vertical", + "axis": [ + { + "name": "Gravity-related height", + "abbreviation": "H", + "direction": "up", + "unit": "metre" + } + ] + } + } + ], + "scope": "Spatial referencing.", + "area": "World.", + "bbox": { + "south_latitude": -90, + "west_longitude": -180, + "north_latitude": 90, + "east_longitude": 180 + }, + "id": { + "authority": "EPSG", + "code": 9518 + } + } + +BoundCRS +++++++++ + +The Bound CRS, using as a base EPSG:4258 "ETRS89" geographic CRS, with an +explicit transformation to WGS 84 using a null Helmert transformation, can be expressed as + +.. code-block:: json + + { + "$schema": "https://proj.org/schemas/v0.4/projjson.schema.json", + "type": "BoundCRS", + "source_crs": { + "type": "GeographicCRS", + "name": "ETRS89", + "datum_ensemble": { + "name": "European Terrestrial Reference System 1989 ensemble", + "members": [ + { + "name": "European Terrestrial Reference Frame 1989" + }, + { + "name": "European Terrestrial Reference Frame 1990" + }, + { + "name": "European Terrestrial Reference Frame 1991" + }, + { + "name": "European Terrestrial Reference Frame 1992" + }, + { + "name": "European Terrestrial Reference Frame 1993" + }, + { + "name": "European Terrestrial Reference Frame 1994" + }, + { + "name": "European Terrestrial Reference Frame 1996" + }, + { + "name": "European Terrestrial Reference Frame 1997" + }, + { + "name": "European Terrestrial Reference Frame 2000" + }, + { + "name": "European Terrestrial Reference Frame 2005" + }, + { + "name": "European Terrestrial Reference Frame 2014" + } + ], + "ellipsoid": { + "name": "GRS 1980", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257222101 + }, + "accuracy": "0.1" + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 4258 + } + }, + "target_crs": { + "type": "GeographicCRS", + "name": "WGS 84", + "datum": { + "type": "GeodeticReferenceFrame", + "name": "World Geodetic System 1984", + "ellipsoid": { + "name": "WGS 84", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257223563 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 4326 + } + }, + "transformation": { + "name": "Transformation from unknown to WGS84", + "method": { + "name": "Position Vector transformation (geog2D domain)", + "id": { + "authority": "EPSG", + "code": 9606 + } + }, + "parameters": [ + { + "name": "X-axis translation", + "value": 0, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8605 + } + }, + { + "name": "Y-axis translation", + "value": 0, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8606 + } + }, + { + "name": "Z-axis translation", + "value": 0, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8607 + } + }, + { + "name": "X-axis rotation", + "value": 0, + "unit": { + "type": "AngularUnit", + "name": "arc-second", + "conversion_factor": 4.84813681109536e-06 + }, + "id": { + "authority": "EPSG", + "code": 8608 + } + }, + { + "name": "Y-axis rotation", + "value": 0, + "unit": { + "type": "AngularUnit", + "name": "arc-second", + "conversion_factor": 4.84813681109536e-06 + }, + "id": { + "authority": "EPSG", + "code": 8609 + } + }, + { + "name": "Z-axis rotation", + "value": 0, + "unit": { + "type": "AngularUnit", + "name": "arc-second", + "conversion_factor": 4.84813681109536e-06 + }, + "id": { + "authority": "EPSG", + "code": 8610 + } + }, + { + "name": "Scale difference", + "value": 0, + "unit": { + "type": "ScaleUnit", + "name": "parts per million", + "conversion_factor": 1e-06 + }, + "id": { + "authority": "EPSG", + "code": 8611 + } + } + ] + } + } + +Transformation +++++++++++++++ + +The EPSG:8549 / "NAD27 to NAD83 (8)" transformation can be expressed as: + +.. code-block:: json + + { + "$schema": "https://proj.org/schemas/v0.4/projjson.schema.json", + "type": "Transformation", + "name": "NAD27 to NAD83 (8)", + "source_crs": { + "type": "GeographicCRS", + "name": "NAD27", + "datum": { + "type": "GeodeticReferenceFrame", + "name": "North American Datum 1927", + "ellipsoid": { + "name": "Clarke 1866", + "semi_major_axis": 6378206.4, + "semi_minor_axis": 6356583.8 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 4267 + } + }, + "target_crs": { + "type": "GeographicCRS", + "name": "NAD83", + "datum": { + "type": "GeodeticReferenceFrame", + "name": "North American Datum 1983", + "ellipsoid": { + "name": "GRS 1980", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257222101 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 4269 + } + }, + "method": { + "name": "NADCON5 (2D)", + "id": { + "authority": "EPSG", + "code": 1074 + } + }, + "parameters": [ + { + "name": "Latitude difference file", + "value": "nadcon5.nad27.nad83_1986.alaska.lat.trn.20160901.b", + "id": { + "authority": "EPSG", + "code": 8657 + } + }, + { + "name": "Longitude difference file", + "value": "nadcon5.nad27.nad83_1986.alaska.lon.trn.20160901.b", + "id": { + "authority": "EPSG", + "code": 8658 + } + } + ], + "accuracy": "0.5", + "scope": "Geodesy.", + "area": "United States (USA) - Alaska.", + "bbox": { + "south_latitude": 51.3, + "west_longitude": 172.42, + "north_latitude": 71.4, + "east_longitude": -129.99 + }, + "id": { + "authority": "EPSG", + "code": 8549 + }, + "remarks": "Uses NADCON5 method which expects longitudes positive east in range 0-360°; source and target CRSs have longitudes positive east in range -180° to +180°. Accuracy at 67% confidence level is 0.5m onshore, 5m nearshore and undetermined farther offshore." + } + +Deviations with the WKT2:2019 specification +------------------------------------------- + +While most of this specification is intended to be interoperable with WKT2:2019, +there are a few deviations, reflecting the needs of the PROJ software implementation. + +PROJSON extensions +++++++++++++++++++ + +This specification allows a Bound CRS to be used wherever a CRS object is allowed +in the OGC Topic 2 abstract specification / ISO-19111:2019. In particular, +the members of a coumpound CRS can be a Bound CRS in this specification, whereas +OGC Topic 2 abstract specification restricts it to single CRS. A Bound CRS can +also be used as the source or target of a coordinate operation. + +PROJJSON omissions +++++++++++++++++++ + +This specification does not define an encoding for: +- point motion operations (``POINTMOTIONOPERATION`` WKT keyword) +- triaxial ellipsoid (``TRIAXIAL`` WKT keyword) +- coordinate metadata (``COORDINATEMETADATA`` WKT keyword) + +Reference implementation +------------------------ + +PROJJSON is available as input and output of the `PROJ `_ software since PROJ 6.2. + +The current version is the PROJJSON schema is 0.4.