Package: unijson
Universal JSON Encoder/Decoder for Python ObjectsThis small Python package enables encoding / decoding most Python objects into / from JSON. It offers an API similar to thejsonstandard library package but provides automated functionalities to encode / decode most objects that cannot be converted into JSON by default (e.g. datetimes or custom classes). To do this, it adds two properties__class__and__module__to the generated JSON for all types normally not supported.The rationale for this package is pretty simple: I like to be able to dump/load my objects in an easily readable format pretty much anywhere (e.g. a DB, another program, another Python program). This is particularly practical to use with applications using MongoDB.This package works with Python version 2.7, 3.4, 3.5, 3.6 and 3.7 (the unit tests passed for all those versions). To install it, clone the git and simply usepython setup.py installOR you can also install it viapip install unijsonsince it's also registered on PyPihere.Here is what you can do with this little package.The types already supported byjsonare unchangedAll the types already supported byjsonare supported byunijsonand behave in the exact same way sinceUniversalJSONEncoderuses the defaultJSONEncoderfor all the types already supported.importjson,unijsond={"peuh":123,"pouet":[True,False,None,"ruguhregr"]}# Both will return the same string:json.dumps(d)unijson.dumps(d)Automatically find a way to encode your custom classesUsingunijson, converting your custom classes instances into JSON objects has never been more simple.
For most simple classes, theUniversalJSONEncoderwill find a way to transform them into JSON compliant objects without the need for extra methods.# Define a custom classclassTest(object):def__init__(self,a1,a2):self.a1,self.a2=a1,a2o1=Test(12,34)# json.dumps(o1) would raise an exception.# TypeError: Object of type 'Test' is not JSON serializable# unijson won't blink:unijson.dumps(o1)# {"a1": 12, "a2": 34, "__class__": "Test", "__module__": "examples"}Define encoders / decoders for your custom classesWithunijson, providing encoding / decoding functions for your custom classes is really simple. You just implement__json_encode__()/__json_decode__()in your custom classes. They will then be taken into account automatically by theUniversalJSONEncoder/UniversalJSONDecoder. This can be used to add some extra information into the resulting JSON object, or to provide a way to transform complex object into a JSON-serialisable dictionnary.# Define a custom class that defines methods for the universal serialiser:classDefineMethods(object):def__init__(self,a1,a2):self.a1,self.a2=a1,a2def__json_encode__(self):return{"a1":self.a1,"a2":self.a2,"extra":"for the fun"}@staticmethoddef__json_decode__(d):returnDefineMethods(d["a1"],d["a2"])def__eq__(self,other):returnself.__dict__==other.__dict__o=DefineMethods("whatever",False)s=unijson.dumps(o)# '{"a1": "whatever", "a2": false, "extra": "for the fun", "__class__": "DefineMethods", "__module__": "examples"}'d=unijson.loads(s)# o == d should be TrueHere is what you need to know on the two methods illustrated above:__json_encode__(): should take no argument and return a dictionary of unijson-serialisable objects (remember that many objects are unijson-serialisable by default!).__json_decode__(): should be static, take a single argument (a dict), and return an instance of the class it's defined in.Define and register encoders / decoders for any classIf you use external libraries, or non-JSON-serialisable types from the standard library (e.g. datetime), you might find yourself stuck on a simple way to convert those objects into JSON. Worry no more, my friend, forunijsonhas a solution for that. You can register encoding / decoding functions to theUniversalJSONEncoder/UniversalJSONDecoderto specify how to encode / decode anything.unijsonalready offers a few extra encoders / decoders for all the types found indatetimeandpytz(for the management of timezones). If you have a look atunijson's code, you will find those encoders. Here is an example that demonstrates how to register encoding functions:#Encoding function:defjson_encode_date(d):"""Encoder for dates (from module datetime)."""return{"day":d.day,"month":d.month,"year":d.year}UniversalJSONEncoder.register(datetime.date,json_encode_date)# Won't even require a decoding function since the created dictionnary can be used as arguments to the constructor (that's one of the automated methods used by UniversalJSONDecoder to build objects).If you want to add your own encoders / decoders and register them, the functions you register must do the following:encoders should take single argument (the object to encode) and return a dictionary of UniJSON-serialisable objects.decoders should take a single argument (the dict extracted by the decoder) and return an instance of the decoded object.Additional informationAuthor: Bastien PietropaoliContact:bastien.pietropaoli@gmail.comLicense:Apache v2.0If you have suggestions, remarks, or questions, do not hesitate to contact me.
Also, if you have made nice encoders/decoders that you think could be a good addition to this package, feel free to submit a pull request.