Completed
Push — master ( db4c81...c9ecbe )
by Ramon
25s queued 11s
created

jsons.serializers.default_dict._store_and_hash()   A

Complexity

Conditions 3

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 19
rs 9.7
c 0
b 0
f 0
cc 3
nop 3
1
from typing import Optional, Callable, Dict, Tuple
2
3
from jsons._common_impl import JSON_KEYS
4
from jsons._dump_impl import dump
5
6
7
def default_dict_serializer(
8
        obj: dict,
9
        cls: Optional[type] = None,
10
        *,
11
        strict: bool = False,
12
        strip_nulls: bool = False,
13
        key_transformer: Optional[Callable[[str], str]] = None,
14
        types: Optional[Dict[str, type]] = None,
15
        **kwargs) -> dict:
16
    """
17
    Serialize the given ``obj`` to a dict of serialized objects.
18
    :param obj: the dict that is to be serialized.
19
    :param cls: not used.
20
    :param strict: if ``True`` the serialization will raise upon any the
21
    failure of any attribute. Otherwise it continues with a warning.
22
    :param strict: a bool to determine if the serializer should be strict
23
    (i.e. only dumping stuff that is known to ``cls``).
24
    :param strip_nulls: if ``True`` the resulting dict will not contain null
25
    values.
26
    :param key_transformer: a function that will be applied to all keys in the
27
    resulting dict.
28
    :param types: a ``dict`` with attribute names (keys) and their types
29
    (values).
30
    :param kwargs: any keyword arguments that may be given to the serialization
31
    process.
32
    :return: a dict of which all elements are serialized.
33
    """
34
    result = dict()
35
    types = types or dict()
36
    for key in obj:
37
        obj_ = obj[key]
38
        cls_ = types.get(key, None)
39
40
        # If key is not a valid json type, use the hash as key and store the
41
        # original key in a separate section.
42
        dict_and_key = _store_and_hash(result, key,
43
                                       key_transformer=key_transformer,
44
                                       strip_nulls=strip_nulls, strict=strict,
45
                                       types=types, **kwargs)
46
        if dict_and_key:
47
            result, key = dict_and_key
48
49
        dumped_elem = dump(obj_,
50
                           cls=cls_,
51
                           key_transformer=key_transformer,
52
                           strip_nulls=strip_nulls,
53
                           strict=strict,
54
                           **kwargs)
55
        if not (strip_nulls and dumped_elem is None):
56
            if key_transformer:
57
                key = key_transformer(key)
58
            result[key] = dumped_elem
59
    return result
60
61
62
def _store_and_hash(
63
        obj: dict,
64
        key: object,
65
        **kwargs
66
) -> Optional[Tuple[dict, int]]:
67
    # Store the given key in the given dict under a special section if that
68
    # key is not a valid json key. Return a hash of that key.
69
    result = None
70
    if not any(issubclass(type(key), json_key) for json_key in JSON_KEYS):
71
        # Apparently key is not a valid json key value. Since it got into
72
        # a Python dict without crashing, it must be hashable.
73
        obj_ = {**obj}
74
        key_hash = hash(key)
75
        if '-keys' not in obj_:
76
            obj_['-keys'] = {}
77
        dumped_key = dump(key, **kwargs)
78
        obj_['-keys'][key_hash] = dumped_key
79
        result = (obj_, key_hash)
80
    return result
81