I published a lib on PyPi that does that, which pushed to write a complete
readme, that I will reproduce here if anybody is interested in more
discussion about this, along with my conclusions:

Overall, it seems like the cost of maintenance is going to be
insignificant.

While the value is reduced with objects that can't be patched during
runtime such as datetime (TypeError: can't set attributes of
built-in/extension type 'datetime.datetime') that you'd need to import from
that library instead of from datetime, it still brings value in making
serialization and deserialization into the versatile and popular JSON
format easier and more reusable than with the current object_hook, by
leveraging typical object oriented programing in a very boring way that
makes it easy for anyone to grasp.

The README looks like:

Instead of:

    from json import loads, dumps
    from uuid import UUID, uuid4

    obj = uuid4()
    encoded = dumps(str(obj))
    decoded = UUID(loads(encoded))

    assert obj == decoded

We can do:

    from jsonlight import loads, dumps
    from uuid import UUID, uuid4

    obj = uuid4()
    encoded = dumps(obj)
    decoded = loads(UUID, encoded)
    assert obj == decoded

This is because jsonlight patches uuid.UUID class to add the following
methods:

- ``__jsondump__``: return a representation of self with JSON data types
- ``__jsonload__``: instantiate an object based on the result from
__jsondump__

You can see that the main difference with ``json.loads`` is that
``jsonlight.loads`` requires a type as the first argument. This is because
``jsonlight.loads`` will first call ``json.loads`` to convert the string
into a
Python object with basic JSON types, and then pass that to the type's
``__jsonload__`` function.

Other types can't be monkey patched, so you have to import them from
jsonlight
instead, which is the sad case of datetime:

    from jsonlight import loads, dumps, datetime
    obj = datetime.now()
    assert obj == loads(datetime, dumps(obj))

You may also define ``__jsondump__`` and ``__jsonload__`` methods on your
own
classes, example:

    from jsonlight import load

    class YourClass:
        def __init__(self, uuid=None):
            self.uuid = uuid or uuid4()

        def __jsondump__(self):
            return dict(uuid=self.uuid)

        @classmethod
        def __jsonload__(cls, data):
            return cls(load(UUID, data['uuid'])

            # This also works, but would not illustrate how to support
recursion
            # return cls(UUID(data['uuid']))

As you can see:

- you don't have to worry about calling ``__jsondump__`` on return values of
  your own ``__jsondump__`` because ``jsonlight.dumps`` will do that
  recursively,
- you have full control on deserialization just like with ``__setstate__``,
but if
  you call jsonlight.load in there yourself then you don't have to duplicate
  deserialization logic or bother calling ``__jsonload__`` on nested
objects
  yourself,

Monkey-patched stdlib objects are:

- UUID
- Path

Feel free to add more.

Stdlib objects that couldn't be monkey patched, and that you have to import
from jsonlight instead are:

- datetime
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PL3UN25ASVP5IDSAPK5RGYIBY6GKLWHW/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to