| | import abc |
| | import json |
| | from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union, overload |
| |
|
| | from dataclasses_json.cfg import config, LetterCase |
| | from dataclasses_json.core import (Json, _ExtendedEncoder, _asdict, |
| | _decode_dataclass) |
| | from dataclasses_json.mm import (JsonData, SchemaType, build_schema) |
| | from dataclasses_json.undefined import Undefined |
| | from dataclasses_json.utils import (_handle_undefined_parameters_safe, |
| | _undefined_parameter_action_safe) |
| |
|
| | A = TypeVar('A', bound="DataClassJsonMixin") |
| | T = TypeVar('T') |
| | Fields = List[Tuple[str, Any]] |
| |
|
| |
|
| | class DataClassJsonMixin(abc.ABC): |
| | """ |
| | DataClassJsonMixin is an ABC that functions as a Mixin. |
| | |
| | As with other ABCs, it should not be instantiated directly. |
| | """ |
| | dataclass_json_config: Optional[dict] = None |
| |
|
| | def to_json(self, |
| | *, |
| | skipkeys: bool = False, |
| | ensure_ascii: bool = True, |
| | check_circular: bool = True, |
| | allow_nan: bool = True, |
| | indent: Optional[Union[int, str]] = None, |
| | separators: Optional[Tuple[str, str]] = None, |
| | default: Optional[Callable] = None, |
| | sort_keys: bool = False, |
| | **kw) -> str: |
| | return json.dumps(self.to_dict(encode_json=False), |
| | cls=_ExtendedEncoder, |
| | skipkeys=skipkeys, |
| | ensure_ascii=ensure_ascii, |
| | check_circular=check_circular, |
| | allow_nan=allow_nan, |
| | indent=indent, |
| | separators=separators, |
| | default=default, |
| | sort_keys=sort_keys, |
| | **kw) |
| |
|
| | @classmethod |
| | def from_json(cls: Type[A], |
| | s: JsonData, |
| | *, |
| | parse_float=None, |
| | parse_int=None, |
| | parse_constant=None, |
| | infer_missing=False, |
| | **kw) -> A: |
| | kvs = json.loads(s, |
| | parse_float=parse_float, |
| | parse_int=parse_int, |
| | parse_constant=parse_constant, |
| | **kw) |
| | return cls.from_dict(kvs, infer_missing=infer_missing) |
| |
|
| | @classmethod |
| | def from_dict(cls: Type[A], |
| | kvs: Json, |
| | *, |
| | infer_missing=False) -> A: |
| | return _decode_dataclass(cls, kvs, infer_missing) |
| |
|
| | def to_dict(self, encode_json=False) -> Dict[str, Json]: |
| | return _asdict(self, encode_json=encode_json) |
| |
|
| | @classmethod |
| | def schema(cls: Type[A], |
| | *, |
| | infer_missing: bool = False, |
| | only=None, |
| | exclude=(), |
| | many: bool = False, |
| | context=None, |
| | load_only=(), |
| | dump_only=(), |
| | partial: bool = False, |
| | unknown=None) -> "SchemaType[A]": |
| | Schema = build_schema(cls, DataClassJsonMixin, infer_missing, partial) |
| |
|
| | if unknown is None: |
| | undefined_parameter_action = _undefined_parameter_action_safe(cls) |
| | if undefined_parameter_action is not None: |
| | |
| | unknown = undefined_parameter_action.name.lower() |
| |
|
| | return Schema(only=only, |
| | exclude=exclude, |
| | many=many, |
| | context=context, |
| | load_only=load_only, |
| | dump_only=dump_only, |
| | partial=partial, |
| | unknown=unknown) |
| |
|
| |
|
| | @overload |
| | def dataclass_json(_cls: None = ..., *, letter_case: Optional[LetterCase] = ..., |
| | undefined: Optional[Union[str, Undefined]] = ...) -> Callable[[Type[T]], Type[T]]: ... |
| |
|
| |
|
| | @overload |
| | def dataclass_json(_cls: Type[T], *, letter_case: Optional[LetterCase] = ..., |
| | undefined: Optional[Union[str, Undefined]] = ...) -> Type[T]: ... |
| |
|
| |
|
| | def dataclass_json(_cls: Optional[Type[T]] = None, *, letter_case: Optional[LetterCase] = None, |
| | undefined: Optional[Union[str, Undefined]] = None) -> Union[Callable[[Type[T]], Type[T]], Type[T]]: |
| | """ |
| | Based on the code in the `dataclasses` module to handle optional-parens |
| | decorators. See example below: |
| | |
| | @dataclass_json |
| | @dataclass_json(letter_case=LetterCase.CAMEL) |
| | class Example: |
| | ... |
| | """ |
| |
|
| | def wrap(cls: Type[T]) -> Type[T]: |
| | return _process_class(cls, letter_case, undefined) |
| |
|
| | if _cls is None: |
| | return wrap |
| | return wrap(_cls) |
| |
|
| |
|
| | def _process_class(cls: Type[T], letter_case: Optional[LetterCase], |
| | undefined: Optional[Union[str, Undefined]]) -> Type[T]: |
| | if letter_case is not None or undefined is not None: |
| | cls.dataclass_json_config = config(letter_case=letter_case, |
| | undefined=undefined)['dataclasses_json'] |
| |
|
| | cls.to_json = DataClassJsonMixin.to_json |
| | |
| | |
| | cls.from_json = classmethod(DataClassJsonMixin.from_json.__func__) |
| | cls.to_dict = DataClassJsonMixin.to_dict |
| | cls.from_dict = classmethod(DataClassJsonMixin.from_dict.__func__) |
| | cls.schema = classmethod(DataClassJsonMixin.schema.__func__) |
| |
|
| | cls.__init__ = _handle_undefined_parameters_safe(cls, kvs=(), |
| | usage="init") |
| | |
| | DataClassJsonMixin.register(cls) |
| | return cls |
| |
|