diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2021-09-14 18:13:47 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2021-09-14 18:13:47 +0200 |
| commit | bca0a82921594c675ed1212f54e032f19004ee82 (patch) | |
| tree | 29373bee072524c43091b0b0597d9bd1a74d3006 | |
| parent | 92ca1a9455cdd136aaaeb1dbb0d8d867020e70c6 (diff) | |
| download | PROJ-bca0a82921594c675ed1212f54e032f19004ee82.tar.gz PROJ-bca0a82921594c675ed1212f54e032f19004ee82.zip | |
PROJJSON: support additional properties allowed in id object (version, authority_citation, uri) for parity with WKT2:2019
| -rw-r--r-- | data/projjson.schema.json | 11 | ||||
| -rw-r--r-- | docs/source/apps/cct.rst | 2 | ||||
| -rw-r--r-- | docs/source/apps/cs2cs.rst | 2 | ||||
| -rw-r--r-- | docs/source/apps/projinfo.rst | 2 | ||||
| -rw-r--r-- | docs/source/development/reference/functions.rst | 2 | ||||
| -rw-r--r-- | docs/source/specifications/projjson.rst | 5 | ||||
| -rw-r--r-- | include/proj/io.hpp | 3 | ||||
| -rw-r--r-- | schemas/v0.4/projjson.schema.json | 1002 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 7 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 46 | ||||
| -rw-r--r-- | src/iso19111/metadata.cpp | 26 | ||||
| -rw-r--r-- | test/cli/testprojinfo_out.dist | 2 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 2 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 90 |
14 files changed, 1161 insertions, 41 deletions
diff --git a/data/projjson.schema.json b/data/projjson.schema.json index c347b3e1..6ed97b7b 100644 --- a/data/projjson.schema.json +++ b/data/projjson.schema.json @@ -1,7 +1,7 @@ { - "$id": "https://proj.org/schemas/v0.3/projjson.schema.json", + "$id": "https://proj.org/schemas/v0.4/projjson.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for PROJJSON (v0.3)", + "description": "Schema for PROJJSON (v0.4)", "$comment": "This file exists both in data/ and in schemas/vXXX/. Keep both in sync. And if changing the value of $id, change PROJJSON_CURRENT_VERSION accordingly in io.cpp", "oneOf": [ @@ -612,7 +612,12 @@ "authority": { "type": "string" }, "code": { "oneOf": [ { "type": "string" }, { "type": "integer" } ] - } + }, + "version": { + "oneOf": [ { "type": "string" }, { "type": "number" } ] + }, + "authority_citation": { "type": "string" }, + "uri": { "type": "string" } }, "required" : [ "authority", "code" ], "additionalProperties": false diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst index 75d67972..08bdd004 100644 --- a/docs/source/apps/cct.rst +++ b/docs/source/apps/cct.rst @@ -29,7 +29,7 @@ by :c:func:`proj_create`, provided it expresses a coordinate operation uniqueness is not guaranteed, heuristics are applied to determine the appropriate best match. - a OGC URN combining references for concatenated operations (e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618") - - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json + - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.4/projjson.schema.json .. versionadded:: 8.0.0 diff --git a/docs/source/apps/cs2cs.rst b/docs/source/apps/cs2cs.rst index 00443d9c..841ce092 100644 --- a/docs/source/apps/cs2cs.rst +++ b/docs/source/apps/cs2cs.rst @@ -35,7 +35,7 @@ Synopsis (*added in 6.2*) - a OGC URN combining references for concatenated operations (e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618") - - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json (*added in 6.2*) + - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.4/projjson.schema.json (*added in 6.2*) - a compound CRS made from two object names separated with " + ". e.g. "WGS 84 + EGM96 height" (*added in 7.1*) .. versionadded:: 6.0.0 diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst index f9445f1b..04ee7578 100644 --- a/docs/source/apps/projinfo.rst +++ b/docs/source/apps/projinfo.rst @@ -55,7 +55,7 @@ Synopsis (*added in 6.2*) - a OGC URN combining references for concatenated operations (e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618") - - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json (*added in 6.2*) + - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.4/projjson.schema.json (*added in 6.2*) - a compound CRS made from two object names separated with " + ". e.g. "WGS 84 + EGM96 height" (*added in 7.1*) {object_reference} is a filename preceded by the '@' character. The diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst index 142c7ca9..10bb07d0 100644 --- a/docs/source/development/reference/functions.rst +++ b/docs/source/development/reference/functions.rst @@ -52,7 +52,7 @@ paragraph for more details. syntax "EPSG:2393+5717"), - a OGC URN combining references for concatenated operations (e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618") - - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json (*added in 6.2*) + - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.4/projjson.schema.json (*added in 6.2*) - a compound CRS made from two object names separated with " + ". e.g. "WGS 84 + EGM96 height" (*added in 7.1*) Example call: diff --git a/docs/source/specifications/projjson.rst b/docs/source/specifications/projjson.rst index 13ef19b5..c2280c0b 100644 --- a/docs/source/specifications/projjson.rst +++ b/docs/source/specifications/projjson.rst @@ -13,17 +13,18 @@ the same as WKT2:2019. PROJJSON is available as input and output of PROJ since PROJ 6.2. -The current version is 0.3. +The current version is 0.4. Schema ------ A JSON schema of its grammar is available at -https://proj.org/schemas/v0.3/projjson.schema.json +https://proj.org/schemas/v0.4/projjson.schema.json History ------- +* 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 diff --git a/include/proj/io.hpp b/include/proj/io.hpp index 1c858248..b07f55ff 100644 --- a/include/proj/io.hpp +++ b/include/proj/io.hpp @@ -540,8 +540,7 @@ class PROJ_GCC_DLL JSONFormatter { PROJ_INTERNAL bool outputUsage(bool calledBeforeObjectContext = false) const; - PROJ_INTERNAL static const char *PROJJSON_v0_2; - PROJ_INTERNAL static const char *PROJJSON_v0_3; + PROJ_INTERNAL static const char *PROJJSON_v0_4; //! @endcond diff --git a/schemas/v0.4/projjson.schema.json b/schemas/v0.4/projjson.schema.json new file mode 100644 index 00000000..6ed97b7b --- /dev/null +++ b/schemas/v0.4/projjson.schema.json @@ -0,0 +1,1002 @@ +{ + "$id": "https://proj.org/schemas/v0.4/projjson.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for PROJJSON (v0.4)", + "$comment": "This file exists both in data/ and in schemas/vXXX/. Keep both in sync. And if changing the value of $id, change PROJJSON_CURRENT_VERSION accordingly in io.cpp", + + "oneOf": [ + { "$ref": "#/definitions/crs" }, + { "$ref": "#/definitions/datum" }, + { "$ref": "#/definitions/datum_ensemble" }, + { "$ref": "#/definitions/ellipsoid" }, + { "$ref": "#/definitions/prime_meridian" }, + { "$ref": "#/definitions/single_operation" }, + { "$ref": "#/definitions/concatenated_operation" } + ], + + "definitions": { + + "abridged_transformation": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["AbridgedTransformation"] }, + "name": { "type": "string" }, + "method": { "$ref": "#/definitions/method" }, + "parameters": { + "type": "array", + "items": { "$ref": "#/definitions/parameter_value" } + }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "method", "parameters" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "axis": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["Axis"] }, + "name": { "type": "string" }, + "abbreviation": { "type": "string" }, + "direction": { "type": "string", + "enum": [ "north", + "northNorthEast", + "northEast", + "eastNorthEast", + "east", + "eastSouthEast", + "southEast", + "southSouthEast", + "south", + "southSouthWest", + "southWest", + "westSouthWest", + "west", + "westNorthWest", + "northWest", + "northNorthWest", + "up", + "down", + "geocentricX", + "geocentricY", + "geocentricZ", + "columnPositive", + "columnNegative", + "rowPositive", + "rowNegative", + "displayRight", + "displayLeft", + "displayUp", + "displayDown", + "forward", + "aft", + "port", + "starboard", + "clockwise", + "counterClockwise", + "towards", + "awayFrom", + "future", + "past", + "unspecified" ] }, + "unit": { "$ref": "#/definitions/unit" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "abbreviation", "direction" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "bbox": { + "type": "object", + "properties": { + "east_longitude": { "type": "number" }, + "west_longitude": { "type": "number" }, + "south_latitude": { "type": "number" }, + "north_latitude": { "type": "number" } + }, + "required" : [ "east_longitude", "west_longitude", + "south_latitude", "north_latitude" ], + "additionalProperties": false + }, + + "bound_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["BoundCRS"] }, + "name": { "type": "string" }, + "source_crs": { "$ref": "#/definitions/crs" }, + "target_crs": { "$ref": "#/definitions/crs" }, + "transformation": { "$ref": "#/definitions/abridged_transformation" }, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "source_crs", "target_crs", "transformation" ], + "additionalProperties": false + }, + + "compound_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["CompoundCRS"] }, + "name": { "type": "string" }, + "components": { + "type": "array", + "items": { "$ref": "#/definitions/crs" } + }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "components" ], + "additionalProperties": false + }, + + "concatenated_operation": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["ConcatenatedOperation"] }, + "name": { "type": "string" }, + "source_crs": { "$ref": "#/definitions/crs" }, + "target_crs": { "$ref": "#/definitions/crs" }, + "steps": { + "type": "array", + "items": { "$ref": "#/definitions/single_operation" } + }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "source_crs", "target_crs", "steps" ], + "additionalProperties": false + }, + + "conversion": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["Conversion"] }, + "name": { "type": "string" }, + "method": { "$ref": "#/definitions/method" }, + "parameters": { + "type": "array", + "items": { "$ref": "#/definitions/parameter_value" } + }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "method" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "coordinate_system": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["CoordinateSystem"] }, + "name": { "type": "string" }, + "subtype": { "type": "string", + "enum": ["Cartesian", + "spherical", + "ellipsoidal", + "vertical", + "ordinal", + "parametric", + "TemporalDateTime", + "TemporalCount", + "TemporalMeasure"] }, + "axis": { + "type": "array", + "items": { "$ref": "#/definitions/axis" } + }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "subtype", "axis" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "crs": { + "oneOf": [ + { "$ref": "#/definitions/bound_crs" }, + { "$ref": "#/definitions/compound_crs" }, + { "$ref": "#/definitions/derived_engineering_crs" }, + { "$ref": "#/definitions/derived_geodetic_crs" }, + { "$ref": "#/definitions/derived_parametric_crs" }, + { "$ref": "#/definitions/derived_projected_crs" }, + { "$ref": "#/definitions/derived_temporal_crs" }, + { "$ref": "#/definitions/derived_vertical_crs" }, + { "$ref": "#/definitions/engineering_crs" }, + { "$ref": "#/definitions/geodetic_crs" }, + { "$ref": "#/definitions/parametric_crs" }, + { "$ref": "#/definitions/projected_crs" }, + { "$ref": "#/definitions/temporal_crs" }, + { "$ref": "#/definitions/vertical_crs" } + ] + }, + + "datum": { + "oneOf": [ + { "$ref": "#/definitions/geodetic_reference_frame" }, + { "$ref": "#/definitions/vertical_reference_frame" }, + { "$ref": "#/definitions/dynamic_geodetic_reference_frame" }, + { "$ref": "#/definitions/dynamic_vertical_reference_frame" }, + { "$ref": "#/definitions/temporal_datum" }, + { "$ref": "#/definitions/parametric_datum" }, + { "$ref": "#/definitions/engineering_datum" } + ] + }, + + "datum_ensemble": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["DatumEnsemble"] }, + "name": { "type": "string" }, + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + } + }, + "ellipsoid": { "$ref": "#/definitions/ellipsoid" }, + "accuracy": { "type": "string" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "members", "accuracy" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "derived_engineering_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["DerivedEngineeringCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/engineering_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "derived_geodetic_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["DerivedGeodeticCRS", + "DerivedGeographicCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/geodetic_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "derived_parametric_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["DerivedParametricCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/parametric_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "derived_projected_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["DerivedProjectedCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/projected_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "derived_temporal_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["DerivedTemporalCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/temporal_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "derived_vertical_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["DerivedVerticalCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/vertical_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "dynamic_geodetic_reference_frame": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/geodetic_reference_frame" }], + "properties": { + "type": { "type": "string", "enum": ["DynamicGeodeticReferenceFrame"] }, + "name": {}, + "anchor": {}, + "ellipsoid": {}, + "prime_meridian": {}, + "frame_reference_epoch": { "type": "number" }, + "deformation_model": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "ellipsoid", "frame_reference_epoch" ], + "additionalProperties": false + }, + + "dynamic_vertical_reference_frame": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/vertical_reference_frame" }], + "properties": { + "type": { "type": "string", "enum": ["DynamicVerticalReferenceFrame"] }, + "name": {}, + "anchor": {}, + "frame_reference_epoch": { "type": "number" }, + "deformation_model": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "frame_reference_epoch" ], + "additionalProperties": false + }, + + "ellipsoid": { + "type": "object", + "oneOf":[ + { + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["Ellipsoid"] }, + "name": { "type": "string" }, + "semi_major_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, + "semi_minor_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "semi_major_axis", "semi_minor_axis" ], + "additionalProperties": false + }, + { + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["Ellipsoid"] }, + "name": { "type": "string" }, + "semi_major_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, + "inverse_flattening": { "type": "number" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "semi_major_axis", "inverse_flattening" ], + "additionalProperties": false + }, + { + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["Ellipsoid"] }, + "name": { "type": "string" }, + "radius": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "radius" ], + "additionalProperties": false + } + ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ] + }, + + "engineering_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["EngineeringCRS"] }, + "name": { "type": "string" }, + "datum": { "$ref": "#/definitions/engineering_datum" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "datum" ], + "additionalProperties": false + }, + + "engineering_datum": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["EngineeringDatum"] }, + "name": { "type": "string" }, + "anchor": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name" ], + "additionalProperties": false + }, + + "geodetic_crs": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["GeodeticCRS", "GeographicCRS"] }, + "name": { "type": "string" }, + "datum": { + "oneOf": [ + { "$ref": "#/definitions/geodetic_reference_frame" }, + { "$ref": "#/definitions/dynamic_geodetic_reference_frame" } + ] + }, + "datum_ensemble": { "$ref": "#/definitions/datum_ensemble" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name" ], + "description": "One and only one of datum and datum_ensemble must be provided", + "allOf": [ + { "$ref": "#/definitions/object_usage" }, + { "$ref": "#/definitions/one_and_only_one_of_datum_or_datum_ensemble" } + ], + "additionalProperties": false + }, + + "geodetic_reference_frame": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["GeodeticReferenceFrame"] }, + "name": { "type": "string" }, + "anchor": { "type": "string" }, + "ellipsoid": { "$ref": "#/definitions/ellipsoid" }, + "prime_meridian": { "$ref": "#/definitions/prime_meridian" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "ellipsoid" ], + "additionalProperties": false + }, + + "id": { + "type": "object", + "properties": { + "authority": { "type": "string" }, + "code": { + "oneOf": [ { "type": "string" }, { "type": "integer" } ] + }, + "version": { + "oneOf": [ { "type": "string" }, { "type": "number" } ] + }, + "authority_citation": { "type": "string" }, + "uri": { "type": "string" } + }, + "required" : [ "authority", "code" ], + "additionalProperties": false + }, + + "ids": { + "type": "array", + "items": { "$ref": "#/definitions/id" } + }, + + "method": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["OperationMethod"]}, + "name": { "type": "string" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "id_ids_mutually_exclusive": { + "not": { + "type": "object", + "required": [ "id", "ids" ] + } + }, + + "one_and_only_one_of_datum_or_datum_ensemble": { + "allOf": [ + { + "not": { + "type": "object", + "required": [ "datum", "datum_ensemble" ] + } + }, + { + "oneOf": [ + { "type": "object", "required": ["datum"] }, + { "type": "object", "required": ["datum_ensemble"] } + ] + } + ] + }, + + "object_usage": { + "anyOf": [ + { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "scope": { "type": "string" }, + "area": { "type": "string" }, + "bbox": { "$ref": "#/definitions/bbox" }, + "remarks": { "type": "string" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ] + }, + { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "usages": { "$ref": "#/definitions/usages" }, + "remarks": { "type": "string" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ] + } + ] + }, + + "parameter_value": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["ParameterValue"] }, + "name": { "type": "string" }, + "value": { + "oneOf": [ + { "type": "string" }, + { "type": "number" } + ] + }, + "unit": { "$ref": "#/definitions/unit" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name", "value" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "parametric_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["ParametricCRS"] }, + "name": { "type": "string" }, + "datum": { "$ref": "#/definitions/parametric_datum" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "datum" ], + "additionalProperties": false + }, + + "parametric_datum": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["ParametricDatum"] }, + "name": { "type": "string" }, + "anchor": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name" ], + "additionalProperties": false + }, + + "prime_meridian": { + "type": "object", + "properties": { + "$schema" : { "type": "string" }, + "type": { "type": "string", "enum": ["PrimeMeridian"] }, + "name": { "type": "string" }, + "longitude": { "$ref": "#/definitions/value_in_degree_or_value_and_unit" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + }, + + "single_operation": { + "oneOf": [ + { "$ref": "#/definitions/conversion" }, + { "$ref": "#/definitions/transformation" } + ] + }, + + "projected_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", + "enum": ["ProjectedCRS"] }, + "name": { "type": "string" }, + "base_crs": { "$ref": "#/definitions/geodetic_crs" }, + "conversion": { "$ref": "#/definitions/conversion" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], + "additionalProperties": false + }, + + "temporal_crs": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["TemporalCRS"] }, + "name": { "type": "string" }, + "datum": { "$ref": "#/definitions/temporal_datum" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "datum" ], + "additionalProperties": false + }, + + "temporal_datum": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["TemporalDatum"] }, + "name": { "type": "string" }, + "calendar": { "type": "string" }, + "time_origin": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "calendar" ], + "additionalProperties": false + }, + + "transformation": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["Transformation"] }, + "name": { "type": "string" }, + "source_crs": { "$ref": "#/definitions/crs" }, + "target_crs": { "$ref": "#/definitions/crs" }, + "interpolation_crs": { "$ref": "#/definitions/crs" }, + "method": { "$ref": "#/definitions/method" }, + "parameters": { + "type": "array", + "items": { "$ref": "#/definitions/parameter_value" } + }, + "accuracy": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name", "source_crs", "target_crs", "method", "parameters" ], + "additionalProperties": false + }, + + "unit": { + "oneOf": [ + { + "type": "string", + "enum": ["metre", "degree", "unity"] + }, + { + "type": "object", + "properties": { + "type": { "type": "string", + "enum": ["LinearUnit", "AngularUnit", "ScaleUnit", + "TimeUnit", "ParametricUnit", "Unit"] }, + "name": { "type": "string" }, + "conversion_factor": { "type": "number" }, + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "required" : [ "type", "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], + "additionalProperties": false + } + ] + }, + + "usages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "scope": { "type": "string" }, + "area": { "type": "string" }, + "bbox": { "$ref": "#/definitions/bbox" } + }, + "additionalProperties": false + } + }, + + "value_and_unit": { + "type": "object", + "properties": { + "value": { "type": "number" }, + "unit": { "$ref": "#/definitions/unit" } + }, + "required" : [ "value", "unit" ], + "additionalProperties": false + }, + + "value_in_degree_or_value_and_unit": { + "oneOf": [ + { "type": "number" }, + { "$ref": "#/definitions/value_and_unit" } + ] + }, + + "value_in_metre_or_value_and_unit": { + "oneOf": [ + { "type": "number" }, + { "$ref": "#/definitions/value_and_unit" } + ] + }, + + "vertical_crs": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["VerticalCRS"] }, + "name": { "type": "string" }, + "datum": { + "oneOf": [ + { "$ref": "#/definitions/vertical_reference_frame" }, + { "$ref": "#/definitions/dynamic_vertical_reference_frame" } + ] + }, + "datum_ensemble": { "$ref": "#/definitions/datum_ensemble" }, + "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "geoid_model": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "interpolation_crs": { "$ref": "#/definitions/crs" }, + "id": { "$ref": "#/definitions/id" } + }, + "required" : [ "name" ], + "additionalProperties": false + }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name"], + "description": "One and only one of datum and datum_ensemble must be provided", + "allOf": [ + { "$ref": "#/definitions/object_usage" }, + { "$ref": "#/definitions/one_and_only_one_of_datum_or_datum_ensemble" } + ], + "additionalProperties": false + }, + + "vertical_reference_frame": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/object_usage" }], + "properties": { + "type": { "type": "string", "enum": ["VerticalReferenceFrame"] }, + "name": { "type": "string" }, + "anchor": { "type": "string" }, + "$schema" : {}, + "scope": {}, + "area": {}, + "bbox": {}, + "usages": {}, + "remarks": {}, + "id": {}, "ids": {} + }, + "required" : [ "name" ], + "additionalProperties": false + } + + } +} diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index be593878..598cedad 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -5528,13 +5528,6 @@ void BoundCRS::_exportToJSON( { auto writer = formatter->writer(); const auto &l_name = nameStr(); - if ((formatter->outputUsage(true) && !domains().empty()) || - (formatter->outputId() && !identifiers().empty()) || - !remarks().empty() || - (!l_name.empty() && l_name != d->baseCRS()->nameStr())) { - // Only upgrades to v0.3 schema if needed - formatter->setSchema(io::JSONFormatter::PROJJSON_v0_3); - } auto objectContext(formatter->MakeObjectContext("BoundCRS", false)); diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 5d7e951e..d3928a86 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -35,6 +35,7 @@ #include <cctype> #include <cmath> #include <cstring> +#include <limits> #include <list> #include <locale> #include <map> @@ -106,14 +107,10 @@ NS_PROJ_START namespace io { //! @cond Doxygen_Suppress -const char *JSONFormatter::PROJJSON_v0_2 = - "https://proj.org/schemas/v0.2/projjson.schema.json"; +const char *JSONFormatter::PROJJSON_v0_4 = + "https://proj.org/schemas/v0.4/projjson.schema.json"; -const char *JSONFormatter::PROJJSON_v0_3 = - "https://proj.org/schemas/v0.3/projjson.schema.json"; - -// v0.2 is our base version. We only upgrade to 0.3 for usage node in BoundCRS -#define PROJJSON_DEFAULT_VERSION JSONFormatter::PROJJSON_v0_2 +#define PROJJSON_DEFAULT_VERSION JSONFormatter::PROJJSON_v0_4 //! @endcond @@ -5398,6 +5395,36 @@ IdentifierNNPtr JSONParser::buildId(const json &j, bool removeInverseOf) { } else { throw ParsingException("Unexpected type for value of \"code\""); } + + if (j.contains("version")) { + auto versionJ = j["version"]; + std::string version; + if (versionJ.is_string()) { + version = versionJ.get<std::string>(); + } else if (versionJ.is_number()) { + const double dblVersion = versionJ.get<double>(); + if (dblVersion >= std::numeric_limits<int>::min() && + dblVersion <= std::numeric_limits<int>::max() && + static_cast<int>(dblVersion) == dblVersion) { + version = internal::toString(static_cast<int>(dblVersion)); + } else { + version = internal::toString(dblVersion); + } + } else { + throw ParsingException("Unexpected type for value of \"version\""); + } + propertiesId.set(Identifier::VERSION_KEY, version); + } + + if (j.contains("authority_citation")) { + propertiesId.set(Identifier::AUTHORITY_KEY, + getString(j, "authority_citation")); + } + + if (j.contains("uri")) { + propertiesId.set(Identifier::URI_KEY, getString(j, "uri")); + } + return Identifier::create(code, propertiesId); } @@ -10709,10 +10736,7 @@ JSONFormatter &JSONFormatter::setIndentationWidth(int width) noexcept { * If set to empty string, it will not be written. */ JSONFormatter &JSONFormatter::setSchema(const std::string &schema) noexcept { - // Upgrade only to v0.3 if the default was v0.2 - if (schema != PROJJSON_v0_3 || d->schema_ == PROJJSON_v0_2) { - d->schema_ = schema; - } + d->schema_ = schema; return *this; } diff --git a/src/iso19111/metadata.cpp b/src/iso19111/metadata.cpp index e8ce37c6..fc1b103f 100644 --- a/src/iso19111/metadata.cpp +++ b/src/iso19111/metadata.cpp @@ -41,6 +41,7 @@ #include "proj_json_streaming_writer.hpp" #include <algorithm> +#include <limits> #include <memory> #include <string> #include <vector> @@ -1114,6 +1115,31 @@ void Identifier::_exportToJSON(JSONFormatter *formatter) const { } catch (const std::exception &) { writer->Add(l_code); } + + if (version().has_value()) { + const auto l_version = *(version()); + writer->AddObjKey("version"); + try { + const double dblVersion = c_locale_stod(l_version); + if (dblVersion >= std::numeric_limits<int>::min() && + dblVersion <= std::numeric_limits<int>::max() && + static_cast<int>(dblVersion) == dblVersion) { + writer->Add(static_cast<int>(dblVersion)); + } else { + writer->Add(dblVersion); + } + } catch (const std::exception &) { + writer->Add(l_version); + } + } + if (authority().has_value() && *(authority()->title()) != l_codeSpace) { + writer->AddObjKey("authority_citation"); + writer->Add(*(authority()->title())); + } + if (uri().has_value()) { + writer->AddObjKey("uri"); + writer->Add(*(uri())); + } } } diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index 6c3a37c4..2405462d 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -160,7 +160,7 @@ GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.25722 PROJJSON: { - "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", + "$schema": "https://proj.org/schemas/v0.4/projjson.schema.json", "type": "GeographicCRS", "name": "WGS 84", "datum_ensemble": { diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 721c54d5..600f47ff 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -4288,7 +4288,7 @@ TEST_F(CApi, proj_as_projjson) { EXPECT_EQ(std::string(projjson), "{\n" " \"$schema\": " - "\"https://proj.org/schemas/v0.2/projjson.schema.json\",\n" + "\"https://proj.org/schemas/v0.4/projjson.schema.json\",\n" " \"type\": \"Ellipsoid\",\n" " \"name\": \"WGS 84\",\n" " \"semi_major_axis\": 6378137,\n" diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 791a8b9e..a4fb5f6e 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -12035,12 +12035,9 @@ TEST(json_import, compound_crs) { // --------------------------------------------------------------------------- TEST(json_import, bound_crs) { - // Explicitly check that the version is v0.2 in that circumstance. Might - // require adjustments in the future. auto json = "{\n" - " \"$schema\": " - "\"https://proj.org/schemas/v0.2/projjson.schema.json\",\n" + " \"$schema\": \"foo\",\n" " \"type\": \"BoundCRS\",\n" " \"source_crs\": {\n" " \"type\": \"GeographicCRS\",\n" @@ -12134,18 +12131,17 @@ TEST(json_import, bound_crs) { auto obj = createFromUserInput(json, nullptr); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(obj); ASSERT_TRUE(boundCRS != nullptr); - EXPECT_EQ(boundCRS->exportToJSON(JSONFormatter::create().get()), json); + EXPECT_EQ( + boundCRS->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); } // --------------------------------------------------------------------------- TEST(json_import, bound_crs_with_name_and_usage) { - // Explicitly check that the version is v0.3 in that circumstance. Might - // require adjustments in the future. auto json = "{\n" - " \"$schema\": " - "\"https://proj.org/schemas/v0.3/projjson.schema.json\",\n" + " \"$schema\": \"foo\",\n" " \"type\": \"BoundCRS\",\n" " \"name\": \"my bound crs\",\n" " \"source_crs\": {\n" @@ -12252,7 +12248,9 @@ TEST(json_import, bound_crs_with_name_and_usage) { auto obj = createFromUserInput(json, nullptr); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(obj); ASSERT_TRUE(boundCRS != nullptr); - EXPECT_EQ(boundCRS->exportToJSON(JSONFormatter::create().get()), json); + EXPECT_EQ( + boundCRS->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); } // --------------------------------------------------------------------------- @@ -13919,6 +13917,78 @@ TEST(json_import, derived_temporal_crs) { // --------------------------------------------------------------------------- +TEST(json_import, id) { + auto json = "{\n" + " \"$schema\": \"foo\",\n" + " \"type\": \"Ellipsoid\",\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563,\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 6326,\n" + " \"version\": 1,\n" + " \"authority_citation\": \"my citation\",\n" + " \"uri\": \"my uri\"\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto ellps = nn_dynamic_pointer_cast<Ellipsoid>(obj); + ASSERT_TRUE(ellps != nullptr); + EXPECT_EQ(ellps->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, id_code_string_version_string) { + auto json = "{\n" + " \"$schema\": \"foo\",\n" + " \"type\": \"Ellipsoid\",\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563,\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": \"abc\",\n" + " \"version\": \"def\",\n" + " \"authority_citation\": \"my citation\",\n" + " \"uri\": \"my uri\"\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto ellps = nn_dynamic_pointer_cast<Ellipsoid>(obj); + ASSERT_TRUE(ellps != nullptr); + EXPECT_EQ(ellps->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, id_code_string_version_double) { + auto json = "{\n" + " \"$schema\": \"foo\",\n" + " \"type\": \"Ellipsoid\",\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563,\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": \"abc\",\n" + " \"version\": 9.8,\n" + " \"authority_citation\": \"my citation\",\n" + " \"uri\": \"my uri\"\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto ellps = nn_dynamic_pointer_cast<Ellipsoid>(obj); + ASSERT_TRUE(ellps != nullptr); + EXPECT_EQ(ellps->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); +} + +// --------------------------------------------------------------------------- + TEST(json_import, multiple_ids) { auto json = "{\n" " \"$schema\": \"foo\",\n" |
