Source code for aas_core3_2.jsonvalueverification

"""
Verify that a value is JSON-able.

A JSON-able value is, recursively, exactly as JSON itself is defined:
a ``None`` (JSON null), a boolean, a finite number, a string, an array of
JSON-able values or an object of JSON-able values with string keys. Python offers no type which
says exactly that, so a value has to be walked to make sure of it.

This module depends on no class of the meta-model. It is invoked from
the ordinary per-class dispatch of
:py:mod:`aas_core3_2.verification`, exactly as every other kind
of property is -- save for the keys of a ``JSONObject`` with a constrained
primitive as its key, which the verification checks itself, by reusing
the function it already generated for that constrained primitive.
"""

# This code has been automatically generated by aas-core-codegen.
# Do NOT edit or append.


import collections.abc
import math
from typing import Iterator

import aas_core3_2.common as our_common
import aas_core3_2.types as our_types
from aas_core3_2.reporting import Error, IndexSegment, KeySegment


[docs]def verify_json_value(value: our_types.JsonValue) -> Iterator[Error]: """ Verify that :paramref:`value` is a JSON-able value, at any depth. The path of an error points into :paramref:`value` itself: an item of an array contributes an index segment and a member of an object a key segment, so that the path leads all the way down to the culprit. The value is walked depth first, so an error deep inside the first member is reported before an error on the second one. The errors thus come in the order in which a reader meets them going through the value. :param value: to be verified :yield: errors, if any """ if value is None: return # NOTE (mristin): # A ``bool`` is an ``int`` in Python, so it has to be checked first -- # otherwise every boolean would be taken for a number. if isinstance(value, bool): return if isinstance(value, int): # NOTE (mristin): # JSON knows a single numeric type, so an ``int`` becomes a ``float`` # on the way out. Only an ``int`` which that conversion can not carry # exactly is an error here -- see # :py:func:`.common.try_to_convert_int_to_float`. if our_common.try_to_convert_int_to_float(value) is None: yield Error( f"Expected a JSON-able value, but got the integer {value}, " f"which is not exactly representable as a JSON number" ) return if isinstance(value, float): # NOTE (mristin): # JSON knows neither an infinity nor a not-a-number, so neither is # a JSON-able value, even though a Python ``float`` is happy to hold # either. if not math.isfinite(value): yield Error( f"Expected a JSON-able value, but got the number {value}, " f"which is neither finite nor representable in JSON" ) return if isinstance(value, str): return if isinstance(value, (dict, collections.abc.Mapping)): for key, item_value in value.items(): if not isinstance(key, str): # NOTE (mristin): # There is no key segment to report here: a key which is no # string names nothing which the path could descend into, so # the path stops at the object which holds it. yield Error( f"Expected only string keys in a JSON-able object, but got " f"a key of type: {type(key)}" ) continue for error in verify_json_value(item_value): error.path._prepend(KeySegment(value, key)) yield error return array_like = our_common.try_to_cast_to_array_like(value) if array_like is not None: for i, item_value in enumerate(array_like): for error in verify_json_value(item_value): error.path._prepend(IndexSegment(array_like, i)) yield error return yield Error( f"Expected a JSON-able value (a null, a boolean, a number, a string, " f"an array or an object), but got: {type(value)}" )
[docs]def verify_json_array(value: our_types.JsonArray) -> Iterator[Error]: """ Verify that :paramref:`value` is a JSON-able array. :param value: to be verified :yield: errors, if any """ if our_common.try_to_cast_to_array_like(value) is None: yield Error(f"Expected a JSON-able array, but got: {type(value)}") return yield from verify_json_value(value)
[docs]def verify_json_object(value: our_types.JsonObject) -> Iterator[Error]: """ Verify that :paramref:`value` is a JSON-able object. :param value: to be verified :yield: errors, if any """ if not isinstance(value, (dict, collections.abc.Mapping)): yield Error(f"Expected a JSON-able object, but got: {type(value)}") return yield from verify_json_value(value)