|
| 1 | +# GeoSciML JSON Code Sprint — project notes for Claude |
| 2 | + |
| 3 | +## What this repo is |
| 4 | + |
| 5 | +Development of a JSON encoding for GeoSciML 4.1, initially in support of the |
| 6 | +May 2026 OGC Builder Days Code Sprint. The main artefacts are JSON Schemas |
| 7 | +(under `schemas/`) and conformant example instances (under `examples/`). |
| 8 | + |
| 9 | +Reference GML 4.1 instances live in the sibling directory |
| 10 | +`../schemas.opengis.net/gsml/4.1/instances/`. Always read the relevant GML |
| 11 | +file before writing a new example for a given type. |
| 12 | + |
| 13 | +## Repository layout |
| 14 | + |
| 15 | +``` |
| 16 | +schemas/json/4.1/ JSON Schema documents (one per feature family) |
| 17 | +examples/json/4.1/ |
| 18 | + <schema-name>/ Individual feature examples for that schema |
| 19 | + featurecollections/ |
| 20 | + <schema-name>/ FeatureCollection examples for that schema |
| 21 | + validation_report.txt Last recorded validate.py run |
| 22 | +validate.py Validation script (see below) |
| 23 | +venv/ Python venv with jsonschema installed |
| 24 | +.schema_cache/ Remote schema cache — auto-populated, git-ignored |
| 25 | +``` |
| 26 | + |
| 27 | +Each schema file `schemas/json/4.1/<name>.json` has a companion example |
| 28 | +directory `examples/json/4.1/<name>/` (individual features) and optionally |
| 29 | +`examples/json/4.1/featurecollections/<name>/` (FeatureCollection documents). |
| 30 | + |
| 31 | +## Validation |
| 32 | + |
| 33 | +```bash |
| 34 | +venv/bin/python validate.py |
| 35 | +``` |
| 36 | + |
| 37 | +The script maps each example directory to its schema, fetches remote dependency |
| 38 | +schemas (json-fg, SWE Common) on first run, caches them under `.schema_cache/`, |
| 39 | +and exits with code 1 if any file fails. |
| 40 | + |
| 41 | +Always run validation before committing and update the recorded report: |
| 42 | + |
| 43 | +```bash |
| 44 | +venv/bin/python validate.py > examples/json/4.1/validation_report.txt |
| 45 | +``` |
| 46 | + |
| 47 | +## Adding a new example directory |
| 48 | + |
| 49 | +1. Create `examples/json/4.1/<schema-name>/` for individual features, or |
| 50 | + `examples/json/4.1/featurecollections/<schema-name>/` for collections. |
| 51 | +2. Register the directory in `validate.py` by adding an entry to `DIR_SCHEMA`: |
| 52 | + ```python |
| 53 | + EXAMPLES_DIR / "<schema-name>": f"{_BASE}/<schema-name>.json", |
| 54 | + EXAMPLES_DIR / "featurecollections/<schema-name>": f"{_BASE}/<schema-collection-name>.json", |
| 55 | + ``` |
| 56 | + The validator automatically treats any path containing `featurecollections` |
| 57 | + as a collection (validated against the schema's top-level `$ref`); individual |
| 58 | + features are narrowed to the `$anchor` matching their `featureType`. |
| 59 | +3. Run the validator to confirm the new directory is picked up. |
| 60 | + |
| 61 | +## Writing a new example instance |
| 62 | + |
| 63 | +### General structure (JSON-FG feature) |
| 64 | + |
| 65 | +Every feature follows the JSON-FG feature structure: |
| 66 | + |
| 67 | +```json |
| 68 | +{ |
| 69 | + "type": "Feature", |
| 70 | + "featureType": "<TypeName>", |
| 71 | + "id": "<unique-string>", |
| 72 | + "geometry": { <GeoJSON geometry in WGS84, or null> }, |
| 73 | + "place": { <geometry in local CRS — omit entirely if WGS84-only> }, |
| 74 | + "coordRefSys": "<CRS URI — only when place is present, at Feature level>", |
| 75 | + "time": null, |
| 76 | + "properties": { ... } |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +- `featureType` must match a `$anchor` in the target schema. |
| 81 | +- `geometry` uses WGS84 lon/lat. `place` is only for non-WGS84 geometries; |
| 82 | + declare the CRS with `coordRefSys` **at the Feature level**, never inside the |
| 83 | + geometry object itself (json-fg prohibits it there). |
| 84 | +- Purely descriptive features (e.g. GeologicUnit, GeologicEvent) typically have |
| 85 | + `geometry: null` and no `place`. |
| 86 | + |
| 87 | +### SWE Common encoding |
| 88 | + |
| 89 | +SWE Category, Quantity, and QuantityRange objects all require `type`, |
| 90 | +`definition` (a URI), and `label` (a string). Quantity and QuantityRange also |
| 91 | +require `uom`. Missing any of these causes a validation failure. |
| 92 | + |
| 93 | +```json |
| 94 | +{ "type": "Category", "definition": "http://...", "label": "...", "value": "http://..." } |
| 95 | +{ "type": "Quantity", "definition": "http://...", "label": "...", "uom": {"code": "m"}, "value": 100.0 } |
| 96 | +{ "type": "QuantityRange", "definition": "http://...", "label": "...", "uom": {"code": "%"}, "value": [5.0, 50.0] } |
| 97 | +``` |
| 98 | + |
| 99 | +### Links vs inline objects |
| 100 | + |
| 101 | +Properties that accept either a reference or an embedded object use |
| 102 | +`oneOf [SCLinkObject, <Type>]`. An SCLinkObject requires `href`: |
| 103 | + |
| 104 | +```json |
| 105 | +{ "href": "http://...", "title": "Human readable label" } |
| 106 | +``` |
| 107 | + |
| 108 | +Use a link when the target is defined elsewhere; use an inline object when the |
| 109 | +value is self-contained in the example. |
| 110 | + |
| 111 | +### Lite schema specifics |
| 112 | + |
| 113 | +All Lite properties are flat strings, numbers, or URIs — no nested SWE objects. |
| 114 | +Properties suffixed `_uri` take a concept URI; the un-suffixed twin is a |
| 115 | +human-readable string. |
| 116 | + |
| 117 | +The Lite schema's `place` references `geometry-object.json` directly (no null |
| 118 | +branch), so omit `place` entirely when the geometry is WGS84-only. Add |
| 119 | +`place` + `coordRefSys` (at Feature level) to show a non-WGS84 geometry. |
| 120 | + |
| 121 | +### Feature collections |
| 122 | + |
| 123 | +Homogeneous (single type): put `featureType` at the collection level. |
| 124 | +Mixed: omit `featureType` from the collection; each feature carries its own. |
| 125 | + |
| 126 | +## Vocabulary URIs |
| 127 | + |
| 128 | +Use CGI / INSPIRE / ICS URIs consistently. Common bases: |
| 129 | + |
| 130 | +| Vocabulary | Base URI | |
| 131 | +|---|---| |
| 132 | +| CGI simple lithology | `http://resource.geosciml.org/classifier/cgi/simplelithology/` | |
| 133 | +| CGI geologic unit type | `http://resource.geosciml.org/classifier/cgi/geologicunittype/` | |
| 134 | +| CGI stratigraphic rank | `http://resource.geosciml.org/classifier/cgi/stratigraphicrank/` | |
| 135 | +| CGI event process | `http://resource.geosciml.org/classifier/cgi/eventprocess/` | |
| 136 | +| CGI fault type | `http://resource.geosciml.org/classifier/cgi/faulttype/` | |
| 137 | +| CGI contact type | `http://resource.geosciml.org/classifier/cgi/contacttype/` | |
| 138 | +| ICS chart (ages) | `http://resource.geosciml.org/classifier/ics/ischart/` | |
| 139 | +| INSPIRE description purpose | `http://inspire.ec.europa.eu/codelist/DescriptionPurpose/` | |
| 140 | +| INSPIRE composition part role | `http://inspire.ec.europa.eu/codelist/CompositionPartRoleValue/` | |
0 commit comments