]> ToastFreeware Gitweb - philipp/winterrodeln/wrpylib.git/blobdiff - wrpylib/json_tools.py
Show notes for public transport and parking.
[philipp/winterrodeln/wrpylib.git] / wrpylib / json_tools.py
index fc6223f1ec0d46aac5cd356809c4d6ffb7fe61b0..f4aa192887596d545bc2ae80ee7d8bd9c82fc81a 100644 (file)
@@ -12,6 +12,49 @@ def _fmt_path(path: List) -> str:
     return f'schema[{"][".join(map(repr, path))}]'
 
 
+def _resolve_ref_not_recursive(sub_schema: JsonTypes, schema: JsonTypes) -> JsonTypes:
+    """In case the sub_schema is a dict and has direct "$ref" keys,
+    it is replaced by a dict where the "$ref" key is replaced by the corresponding definition in schema.
+    Nested $ref keys are not resolved.
+    Recursive $ref keys are not resolved.
+
+    :param sub_schema: JSON sub-schema where a "$ref" key is possible replaced.
+        The value of "$ref" could be e.g. "#/definitions/position"
+    :param schema: JSON root schema containing definitions for the keys.
+    :raise ValidationError: In case a "$ref" could not be resolved.
+    """
+    if not isinstance(sub_schema, dict) or '$ref' not in sub_schema:
+        return sub_schema
+    ref = sub_schema['$ref']
+    if not isinstance(ref, str):
+        raise ValidationError(f'Type of reference {ref} is not string.')
+    path = ref.split('/')
+    if len(path) == 0 or path[0] != '#':
+        raise ValidationError(f'Unsupported reference {ref}.')
+    ref_schema = schema
+    for p in path[1:]:
+        if not isinstance(ref_schema, dict) or p not in ref_schema:
+            raise ValidationError(f'Reference path {ref} not found in schema.')
+        ref_schema = ref_schema[p]
+    if not isinstance(ref_schema, dict):
+        raise ValidationError(f'Reference path {ref} is no dict.')
+    sub_schema = sub_schema.copy()
+    del sub_schema['$ref']
+    resolved_schema = ref_schema.copy()
+    resolved_schema.update(sub_schema)
+    return resolved_schema
+
+
+def _resolve_ref(sub_schema: JsonTypes, schema: JsonTypes) -> JsonTypes:
+    """Same as `_resolve_ref_not_recursive` but recursively resolves $ref keys.
+    However, does not resolve nested $ref keys.
+    """
+    resolved_schema = sub_schema
+    while isinstance(resolved_schema, dict) and '$ref' in resolved_schema:
+        resolved_schema = _resolve_ref_not_recursive(resolved_schema, schema)
+    return resolved_schema
+
+
 def _order_json_keys_string(sub_value: JsonTypes, sub_schema: JsonTypes, schema: JsonTypes, path: List) -> str:
     if not isinstance(sub_value, str):
         raise ValidationError(f'Type of {_fmt_path(path)} needs to be string (Python str).')
@@ -70,9 +113,12 @@ def _order_json_keys(sub_value: JsonTypes, sub_schema: JsonTypes, schema: JsonTy
         if sub_schema:
             return sub_value
         raise ValidationError(f'Value {sub_value} not allowed in {_fmt_path(path)}.')
+    if isinstance(sub_schema, dict):
+        sub_schema = _resolve_ref(sub_schema, schema)
     return {
         'string': _order_json_keys_string,
         'number': _order_json_keys_number,
+        'integer': _order_json_keys_number,
         'object': _order_json_keys_object,
         'array': _order_json_keys_array,
         'boolean': _order_json_keys_boolean,