1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
"""A non-standard "typeof" filter function."""
from typing import Mapping
from typing import Sequence
from jsonpath.filter import UNDEFINED
from jsonpath.filter import UNDEFINED_LITERAL
from jsonpath.function_extensions import ExpressionType
from jsonpath.function_extensions import FilterFunction
from jsonpath.match import NodeList
class TypeOf(FilterFunction):
"""A non-standard "typeof" filter function.
Arguments:
single_number_type: If True, will return "number" for ints and floats,
otherwise we'll use "int" and "float" respectively. Defaults to `True`.
"""
arg_types = [ExpressionType.NODES]
return_type = ExpressionType.VALUE
def __init__(self, *, single_number_type: bool = True) -> None:
self.single_number_type = single_number_type
def __call__(self, nodes: NodeList) -> str: # noqa: PLR0911
"""Return the type of _obj_ as a string.
The strings returned from this function use JSON terminology, much
like the result of JavaScript's `typeof` operator.
"""
if not nodes:
return "undefined"
obj = nodes.values_or_singular()
if obj is UNDEFINED or obj is UNDEFINED_LITERAL:
return "undefined"
if obj is None:
return "null"
if isinstance(obj, str):
return "string"
if isinstance(obj, Sequence):
return "array"
if isinstance(obj, Mapping):
return "object"
if isinstance(obj, bool):
return "boolean"
if isinstance(obj, int):
return "number" if self.single_number_type else "int"
if isinstance(obj, float):
return "number" if self.single_number_type else "float"
return "object"
|