File: json_encoding.rst

package info (click to toggle)
quart 0.20.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,888 kB
  • sloc: python: 8,644; makefile: 42; sh: 17; sql: 6
file content (64 lines) | stat: -rw-r--r-- 1,772 bytes parent folder | download | duplicates (3)
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
55
56
57
58
59
60
61
62
63
64
.. _json_encoding:

JSON Encoding
=============

It is often useful to be able to control how objects are encoded to
and decoded from JSON. Quart makes this possible via a JSONProvider
:class:`~quart.json.provider.JSONProvider`.

Money example
-------------

As an example lets consider a Money object,

.. code-block:: python

    class Money:

        def __init__(self, amount: Decimal, currency: str) -> None:
            self.amount = amount
            self.currency = currency

which we desire to translate to JSON as,

.. code-block:: json

    {
      "amount": "10.00",
      "currency": "GBP"
    }

using encoders and decoders as so,

.. code-block:: python

    from quart.json.provider import _default, DefaultJSONProvider


    class MoneyJSONProvider(DefaultJSONProvider):

        @staticmethod
        def default(object_):
            if isinstance(object_, date):
                return http_date(object_)
            if isinstance(object_, (Decimal, UUID)):
                return str(object_)
            if is_dataclass(object_):
                return asdict(object_)
            if hasattr(object_, "__html__"):
                return str(object_.__html__())
            if isinstance(object_, Money):
                return {'amount': object_.amount, 'currency': object_.currency}

            raise TypeError(f"Object of type {type(object_).__name__} is not JSON serializable")

        @staticmethod
        def dict_to_object(dict_):
            if 'amount' in dict_ and 'currency' in dict_:
                return Money(Decimal(dict_['amount']), dict_['currency'])
            else:
                return dict_

        def loads(self, object_, **kwargs):
            return super().loads(object_, object_hook=self.dict_to_object, **kwargs)