Package: jsonlight
Adds support for a couple of new Python magic methods to make Python object
oriented JSON encoding and decoding a bit easier, with the following goals in
mind:jsonlight.dumps should always work, even if it has to fallback to a stringit detects if an object being dumped defines a__jsondump__methodit detects if an object being dumped is of a type defined in the global
typemap, or the one that’s being usedfor complete round-tripping, the type schema is maintained in a__jsonload__method that you must implementStandard typesThis is what you can already do in Python:fromjsonimportloads,dumpsfromuuidimportUUID,uuid4obj=uuid4()assertobj==UUID(loads(dumps(str(obj))))All standard Python types such as UUID must have an encode/decode method in the
default typemap provided by jsonlight, so encoding to JSON should always work.
However, the type must be specified on load:fromjsonlightimportloads,dumpsfromuuidimportUUID,uuid4obj=uuid4()assertobj==loads(UUID,dumps(obj))You can see that the main difference withjson.loadsis thatjsonlight.loadsrequires a type as first argument. This is becausejsonlight.loadswill first calljson.loadsto convert the string into a
Python object with basic JSON tyes, and then pass that to the type’s__jsonload__function.Nested typesYou may leverage the__jsondump__and__jsonload__methods based on the
following conventions:__jsondump__: return a representation of self with JSON data types__jsonload__: instanciate an object based on the result from __jsondump__Example:fromjsonlightimportloadclassYourClass:def__init__(self):self.now=datetime.now()def__jsondump__(self):returndict(now=self.now)@classmethoddef__jsonload__(cls,data):returncls(load(datetime,data['now'])As you can see:you don’t have to worry about calling__jsondump__on return values of
your own__jsondump__becausejsonlight.dumpswill 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 on nested objects,TypemapsThis lib must support all standard Python types, and it already works for
things like UUID or Path because they cast fine from and to strings. However,
this is not the case for datetimes and there is no JSON standard for datetimes.Since it is a requirement for jsonlight to support all standard python types, a
default typemap is also included, which makes datetimes export to string with.isoformat()and from string with.fromisoformat():now=datetime.now()assertnow==loads(datetime,dumps(now))This is the reason why we have typemaps. The typemap in jsonlight maps a Python
type to a couple of encoding/decoding functions, so that we have something that
works without monkey patching.To illustrate how to use a specific typemap, let’s decide we want to remove the
leading slash of all Path objects dumps and ensure there is one on load, we
will define our own typemap:typemap={Path:(lambdavalue:str(value).lstrip('/'),lambdadata:Path('/'+data.lstrip('/')),),}assertdumps(Path('/foo/bar'),typemap)=='"foo/bar"'assertloads(Path,'"foo/bar"',typemap)A couple of possibilities are left to keep in mind:typemap.update(jsonlight.typemap)adds the default jsonlight typemap to
your own,jsonlight.typemap.update(typemap)adds your own typemap on top of the
default typemap.