121 lines
3.0 KiB
Python
121 lines
3.0 KiB
Python
import abc
|
|
from pathlib import Path
|
|
from typing import Any, List, Dict, Union, TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
JSON_OBJECT = Dict[str, 'JSON']
|
|
JSON_ARRAY = List['JSON']
|
|
JSON = Union[None, bool, int, float, str, 'JSON_ARRAY', 'JSON_OBJECT']
|
|
|
|
else:
|
|
JSON_OBJECT = Dict[str, Any]
|
|
JSON_ARRAY = List[Any]
|
|
JSON = Any
|
|
|
|
|
|
class JsonSerialize(metaclass=abc.ABCMeta):
|
|
__slots__ = ()
|
|
|
|
@abc.abstractmethod
|
|
def as_json(self) -> JSON:
|
|
"""class instance transform to json object.
|
|
|
|
:return: json object
|
|
"""
|
|
pass
|
|
|
|
@classmethod
|
|
def to_json(cls, json: Any):
|
|
"""object *json* to json format.
|
|
|
|
**mapping**
|
|
|
|
=============== ================
|
|
python type json type
|
|
=============== ================
|
|
None null
|
|
bool boolean
|
|
int int
|
|
float float
|
|
str String
|
|
list array
|
|
set set_object [1]_
|
|
dict object
|
|
JsonSerialize [2]_
|
|
=============== ================
|
|
|
|
.. [1] special object.
|
|
|
|
::
|
|
|
|
set_object = {
|
|
"set" : [value]
|
|
}
|
|
|
|
|
|
.. [2] call function :func:`as_json`
|
|
|
|
:param json: json object
|
|
:return: json object
|
|
:raises TypeError: object *json* not a :class:`JsonSerialize`
|
|
"""
|
|
if json is None:
|
|
return None
|
|
|
|
elif isinstance(json, (bool, int, float, str)):
|
|
return json
|
|
|
|
elif isinstance(json, list):
|
|
return [cls.to_json(j) for j in json]
|
|
|
|
elif isinstance(json, dict):
|
|
return {k: cls.to_json(j) for k, j in json.items()}
|
|
|
|
elif isinstance(json, set):
|
|
return {'set': list(json)}
|
|
|
|
elif isinstance(json, Path):
|
|
return str(json)
|
|
|
|
elif isinstance(json, JsonSerialize):
|
|
return json.as_json()
|
|
|
|
else:
|
|
raise TypeError('not a JsonSerialize : ' + type(json).__name__)
|
|
|
|
|
|
def str_json_value(value: JSON) -> str:
|
|
""" utility function to transform json to str value
|
|
|
|
:param value: json object
|
|
:return:
|
|
"""
|
|
if isinstance(value, bool):
|
|
return '1' if value else '0'
|
|
elif isinstance(value, int):
|
|
return str(value)
|
|
elif isinstance(value, str):
|
|
return value
|
|
elif isinstance(value, (list, tuple)):
|
|
return ','.join(map(str_json_value, value))
|
|
else:
|
|
raise RuntimeError('unsupported json form : ' + str(value))
|
|
|
|
|
|
def json_str_value(value: str) -> JSON:
|
|
"""utility function to try to transform str to json value
|
|
|
|
:param value:
|
|
:return: json value
|
|
"""
|
|
if ',' in value:
|
|
return list(map(json_str_value, value.split(',')))
|
|
else:
|
|
try:
|
|
if '.' in value:
|
|
return float(value)
|
|
else:
|
|
return int(value)
|
|
except ValueError:
|
|
return value
|