JSON Schema generation¶
A simple usage of the library that, given generates a JSON Schema for inputs and outputs.
1. Parsing¶
In this sample we'll show the access from a remote public URL.
In [1]:
Copied!
from cwl_loader import load_cwl_from_location
from cwl2ogc import BaseCWLtypes2OGCConverter
workflow_id = 'pattern-12'
cwl_document = load_cwl_from_location('https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl')
workflow = None
for wf in cwl_document:
if workflow_id == wf.id.split('#')[-1]:
workflow = wf
break
if workflow is not None:
cwl_converter = BaseCWLtypes2OGCConverter(workflow)
else:
raise ValueError(f"'#{workflow_id}' not found in input $graph")
from cwl_loader import load_cwl_from_location
from cwl2ogc import BaseCWLtypes2OGCConverter
workflow_id = 'pattern-12'
cwl_document = load_cwl_from_location('https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl')
workflow = None
for wf in cwl_document:
if workflow_id == wf.id.split('#')[-1]:
workflow = wf
break
if workflow is not None:
cwl_converter = BaseCWLtypes2OGCConverter(workflow)
else:
raise ValueError(f"'#{workflow_id}' not found in input $graph")
2026-02-05 18:21:08.012 | DEBUG | cwl_loader:load_cwl_from_location:228 - Loading CWL document from https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl...
2026-02-05 18:21:08.174 | DEBUG | cwl_loader:_load_cwl_from_stream:231 - Reading stream from https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl...
2026-02-05 18:21:08.217 | DEBUG | cwl_loader:load_cwl_from_stream:203 - CWL data of type <class 'ruamel.yaml.comments.CommentedMap'> successfully loaded from stream
2026-02-05 18:21:08.218 | DEBUG | cwl_loader:load_cwl_from_yaml:143 - No needs to update the Raw CWL document since it targets already the v1.2
2026-02-05 18:21:08.218 | DEBUG | cwl_loader:load_cwl_from_yaml:145 - Parsing the raw CWL document to the CWL Utils DOM...
2026-02-05 18:21:09.235 | DEBUG | cwl_loader:load_cwl_from_yaml:158 - Raw CWL document successfully parsed to the CWL Utils DOM!
2026-02-05 18:21:09.236 | DEBUG | cwl_loader:load_cwl_from_yaml:160 - Dereferencing the steps[].run...
2026-02-05 18:21:09.237 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl#crop must be externally imported...
2026-02-05 18:21:09.237 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl - uri: https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl
2026-02-05 18:21:09.237 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl#norm_diff must be externally imported...
2026-02-05 18:21:09.238 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl - uri: https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl
2026-02-05 18:21:09.238 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl#otsu must be externally imported...
2026-02-05 18:21:09.239 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl - uri: https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl
2026-02-05 18:21:09.239 | DEBUG | cwl_loader:load_cwl_from_yaml:167 - steps[].run successfully dereferenced! Dereferencing the FQNs...
2026-02-05 18:21:09.240 | DEBUG | cwl_loader:load_cwl_from_yaml:171 - CWL document successfully dereferenced! Now verifying steps[].run integrity...
2026-02-05 18:21:09.240 | DEBUG | cwl_loader:load_cwl_from_yaml:175 - All steps[].run link are resolvable!
2026-02-05 18:21:09.241 | DEBUG | cwl_loader:load_cwl_from_yaml:178 - Sorting Process instances by dependencies....
2026-02-05 18:21:09.241 | DEBUG | cwl_loader:load_cwl_from_yaml:180 - Sorting process is over.
2026-02-05 18:21:09.241 | DEBUG | cwl_loader:_load_cwl_from_stream:240 - Stream from https://raw.githubusercontent.com/eoap/application-package-patterns/refs/heads/main/cwl-workflow/pattern-12.cwl successfully load!
2. Inputs JSON Schema generation¶
Once the document is parsed, invoke the cwl2ogc APIs to convert the CWL inputs to the JSON schema:
In [2]:
Copied!
import sys
cwl_converter.dump_inputs_json_schema(stream=sys.stdout, pretty_print=True)
import sys
cwl_converter.dump_inputs_json_schema(stream=sys.stdout, pretty_print=True)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eoap.github.io/cwl2ogc/pattern-12/inputs.yaml",
"description": "The schema to represent a pattern-12 inputs definition",
"type": "object",
"required": [
"aoi",
"bands",
"item",
"cropped-collection",
"ndwi-collection",
"water-bodies-collection"
],
"properties": {
"aoi": {
"$ref": "#/$defs/aoi"
},
"bands": {
"$ref": "#/$defs/bands"
},
"item": {
"$ref": "#/$defs/item"
},
"cropped-collection": {
"$ref": "#/$defs/cropped-collection"
},
"ndwi-collection": {
"$ref": "#/$defs/ndwi-collection"
},
"water-bodies-collection": {
"$ref": "#/$defs/water-bodies-collection"
}
},
"additionalProperties": false,
"$defs": {
"aoi": {
"type": "object",
"properties": {
"bbox": {
"type": "array",
"items": {
"type": "number",
"format": "double"
}
},
"crs": {
"type": "string",
"enum": [
"CRS84",
"CRS84h"
]
}
},
"required": [
"bbox",
"crs"
]
},
"bands": {
"type": "array",
"items": {
"type": "string"
},
"default": [
"green",
"nir"
]
},
"item": {
"oneOf": [
{
"type": "string",
"format": "uri"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/collection-spec/json-schema/collection.json"
}
]
},
"cropped-collection": {
"type": "string",
"format": "uri"
},
"ndwi-collection": {
"type": "string",
"format": "uri"
},
"water-bodies-collection": {
"type": "string",
"format": "uri"
}
}
}
2.1 Inputs validation¶
Schema can be used to fully validate an inputs dictionary (expecting JSON Schema validation errors in the example below):
In [3]:
Copied!
from jsonschema import Draft202012Validator
from jsonschema.exceptions import SchemaError
def validate(schema: dict, data: dict):
try:
validator = Draft202012Validator(schema)
errors = validator.iter_errors(data) if validator is not None else []
if errors:
for error in errors:
print(f"[{'.'.join(error.schema_path)}] - #/{'/'.join(error.path)}: {error.message}")
else:
print('No JSON Schema violations detected!')
except SchemaError as schema_error:
print(f"An error occurred while instantiating {Draft202012Validator.__class__.__name__}: {schema_error.message}")
from jsonschema import Draft202012Validator
from jsonschema.exceptions import SchemaError
def validate(schema: dict, data: dict):
try:
validator = Draft202012Validator(schema)
errors = validator.iter_errors(data) if validator is not None else []
if errors:
for error in errors:
print(f"[{'.'.join(error.schema_path)}] - #/{'/'.join(error.path)}: {error.message}")
else:
print('No JSON Schema violations detected!')
except SchemaError as schema_error:
print(f"An error occurred while instantiating {Draft202012Validator.__class__.__name__}: {schema_error.message}")
Define the inputs to be validate
In [4]:
Copied!
inputs = {
"aoi": "-118.985,38.432,-118.183,38.938",
"filesB": "EPSG:4326",
"bands": [ "green", "nir08" ],
"item": "https://planetarycomputer.microsoft.com/api/stac/v1/collections/landsat-c2-l2/items/LC08_L2SP_042033_20231007_02_T1"
}
validate(cwl_converter.get_inputs_json_schema(), inputs)
inputs = {
"aoi": "-118.985,38.432,-118.183,38.938",
"filesB": "EPSG:4326",
"bands": [ "green", "nir08" ],
"item": "https://planetarycomputer.microsoft.com/api/stac/v1/collections/landsat-c2-l2/items/LC08_L2SP_042033_20231007_02_T1"
}
validate(cwl_converter.get_inputs_json_schema(), inputs)
[required] - #/: 'cropped-collection' is a required property [required] - #/: 'ndwi-collection' is a required property [required] - #/: 'water-bodies-collection' is a required property [properties.aoi.type] - #/aoi: '-118.985,38.432,-118.183,38.938' is not of type 'object'
[additionalProperties] - #/: Additional properties are not allowed ('filesB' was unexpected)
3. Outputs JSON Schema generation¶
Users can reuse the BaseCWLtypes2OGCConverter instance to convert the CWL outputs to the JSON Schema:
In [5]:
Copied!
cwl_converter.dump_outputs_json_schema(stream=sys.stdout, pretty_print=True)
cwl_converter.dump_outputs_json_schema(stream=sys.stdout, pretty_print=True)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eoap.github.io/cwl2ogc/pattern-12/outputs.yaml",
"description": "The schema to represent a pattern-12 outputs definition",
"type": "object",
"required": [
"cropped",
"ndwi",
"water_bodies"
],
"properties": {
"cropped": {
"$ref": "#/$defs/cropped"
},
"ndwi": {
"$ref": "#/$defs/ndwi"
},
"water_bodies": {
"$ref": "#/$defs/water_bodies"
}
},
"additionalProperties": false,
"$defs": {
"cropped": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string",
"format": "uri"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/collection-spec/json-schema/collection.json"
}
]
}
},
"ndwi": {
"oneOf": [
{
"type": "string",
"format": "uri"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/collection-spec/json-schema/collection.json"
}
]
},
"water_bodies": {
"oneOf": [
{
"type": "string",
"format": "uri"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json"
},
{
"$ref": "https://schemas.stacspec.org/v1.0.0/collection-spec/json-schema/collection.json"
}
]
}
}
}
2.1 Outputs validation¶
Schema can be used to fully validate an outputs dictionary (JSON Schema validation expected to pass):
In [6]:
Copied!
outputs = {
"example_out": "In girum imus nocte et consumimur igni"
}
validate(cwl_converter.get_outputs_json_schema(), outputs)
outputs = {
"example_out": "In girum imus nocte et consumimur igni"
}
validate(cwl_converter.get_outputs_json_schema(), outputs)
[required] - #/: 'cropped' is a required property
[required] - #/: 'ndwi' is a required property
[required] - #/: 'water_bodies' is a required property
[additionalProperties] - #/: Additional properties are not allowed ('example_out' was unexpected)