Skip to content
Snippets Groups Projects

Extend json-schema model parser

Merged Florian Spreckelsen requested to merge f-enhance-json-parser into dev
Files
5
@@ -192,7 +192,7 @@ def parse_model_from_json_schema(
"""
# @author Florian Spreckelsen
# @date 2022-02-17
# @review Daniel Hornung 2022-02-18
# @review Timm Fitschen 2023-05-25
parser = JsonSchemaParser(types_for_missing_array_items, ignore_unspecified_array_items)
return parser.parse_model_from_json_schema(filename, top_level_recordtype)
@@ -618,14 +618,13 @@ class Parser(object):
class JsonSchemaParser(Parser):
"""Extends the yaml parser to read in datamodels defined in a json schema.
**EXPERIMENTAL:** While this calss can already be used to create data models
**EXPERIMENTAL:** While this class can already be used to create data models
from basic json schemas, there are the following limitations and missing
features:
* Due to limitations of json-schema itself, we currently do not support
inheritance in the imported data models
* The same goes for suggested properties of RecordTypes
* Currently, ``$defs`` and ``$ref`` in the input schema are not resolved.
* Already defined RecordTypes and (scalar) Properties can't be re-used as
list properties
* Reference properties that are different from the referenced RT. (Although
@@ -639,0+638,0 @@
"""
# @author Florian Spreckelsen
# @date 2022-02-17
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
def __init__(self, types_for_missing_array_items={}, ignore_unspecified_array_items=False):
super().__init__()
@@ -665,7 +664,7 @@ class JsonSchemaParser(Parser):
"""
# @author Florian Spreckelsen
# @date 2022-02-17
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
with open(filename, 'r') as schema_file:
model_dict = jsonref.load(schema_file)
@@ -689,7 +688,7 @@ class JsonSchemaParser(Parser):
our : DataModel
The datamodel defined in `model_dict`
"""
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
if isinstance(model_dict, dict):
model_dict = [model_dict]
@@ -711,7 +710,7 @@ class JsonSchemaParser(Parser):
# Check if this is a valid Json Schema
name = self._stringify(elt["title"], context=elt)
self._treat_element(elt, name)
elif "properties" in elt or "patternProperties":
elif "properties" in elt or "patternProperties" in elt:
# No top-level type but there are entities
if "properties" in elt:
for key, prop in elt["properties"].items():
@@ -732,7 +731,7 @@ class JsonSchemaParser(Parser):
return DataModel(self.model.values())
def _get_name_from_property(self, key: str, prop: dict):
# @review Timm Fitschen 2023-05-25
if "title" in prop:
name = self._stringify(prop["title"])
else:
@@ -741,7 +740,7 @@ class JsonSchemaParser(Parser):
return name
def _get_atomic_datatype(self, elt):
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
if elt["type"] == "string":
if "format" in elt and elt["format"] in ["date", "date-time"]:
return db.DATETIME
@@ -761,7 +760,7 @@ class JsonSchemaParser(Parser):
raise JsonSchemaDefinitionError(f"Unkown atomic type in {elt}.")
def _treat_element(self, elt: dict, name: str):
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
force_list = False
if name in self.model:
return self.model[name], force_list
@@ -792,9 +791,6 @@ class JsonSchemaParser(Parser):
ent = self._treat_record_type(elt, name)
elif elt["type"] == "array":
ent, force_list = self._treat_list(elt, name)
elif elt["type"] == "null":
# null
return None, force_list
else:
raise NotImplementedError(
f"Cannot parse items of type '{elt['type']}' (yet).")
@@ -808,7 +804,7 @@ class JsonSchemaParser(Parser):
return ent, force_list
def _treat_record_type(self, elt: dict, name: str):
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
rt = db.RecordType(name=name)
if "required" in elt:
required = elt["required"]
@@ -862,7 +858,7 @@ class JsonSchemaParser(Parser):
return rt
def _treat_list(self, elt: dict, name: str):
# @review Timm Fitschen 2022-02-30
# @review Timm Fitschen 2023-05-25
if "items" not in elt and name not in self.types_for_missing_array_items:
if self.ignore_unspecified_array_items:
@@ -893,6 +889,7 @@ class JsonSchemaParser(Parser):
return db.Property(name=name, datatype=datatype), False
def _get_pattern_prop(self):
# @review Timm Fitschen 2023-05-25
if "__pattern_property_pattern_property" in self.model:
return self.model["__pattern_property_pattern_property"]
pp = db.Property(name="__matched_pattern", datatype=db.TEXT)
@@ -913,12 +910,16 @@ class JsonSchemaParser(Parser):
array.
"""
# @review Timm Fitschen 2023-05-25
num_patterns = len(pattern_elements)
pattern_prop = self._get_pattern_prop()
returns = []
for ii, (key, element) in enumerate(pattern_elements.items()):
name_suffix = f"_{ii+1}" if num_patterns > 1 else ""
name = name_prefix + "Entry" + name_suffix
if "title" not in element:
name_suffix = f"_{ii+1}" if num_patterns > 1 else ""
name = name_prefix + "Entry" + name_suffix
else:
name = element["title"]
if element["type"] == "object":
# simple, is already an object, so can be treated like any other
# record type.
Loading