Package: jsonbind
JsonBindJsonBind is an advanced JSON handling library for Python, designed to enhance the capabilities of the standard json
module. It offers seamless serialization and deserialization of Python data types not typically supported by the default
JSON library, including datetime.datetime, tuples, sets, enumerations (enum), bytes, and custom classes.Installationpip install jsonbindFeaturesCompatibility: Functions prototypes designed to match the standard json library.Extended Data Type Support: Handle complex Python data types effortlessly.Custom Class Serialization: Easily serialize and deserialize your custom classes.Intuitive API: Designed to be familiar to users of the standard json module.The Python JSON standard libraryThe standard JSON library in Python expertly facilitates the serialization and deserialization of JSON data types into
native Python data types, as detailed in the following table:JSON Data TypePython Data Typeobjectdictarrayliststringstrnumberint, floatboolboolnullNoneThis compatibility with JSON significantly enhances its utility for data sharing, communication, and storage purposes.
However, it is important to recognize that the JSON format's inherent limitations in representing more complex data
structures can sometimes restrict its applicability. Crafting specific encoders and decoders to address these
limitations often presents a substantial technical challenge, requiring thoughtful consideration and expertise.Type-bindingsJsonBind operates on the principle of utilizing type bindings to facilitate the transformation between JSON types and
Python types. It comes equipped with an extensive array of pre-defined bindings for commonly used types, including
tuples, sets, datetime objects, bytes, classes, and more. Additionally, JsonBind is designed to simplify the process
of creating new bindings. This flexibility allows users to seamlessly integrate JSON types with novel Python data types,
enhancing the library's adaptability and ease of use in various programming scenarios.To extend the JSON's functionality, multiple bindings can be created for the same json data type.
This allows, for example, strings to be decoded as datetime objects and bytes, object to class dictionaries and instances, etc.Out-of-the-box bindingsJSON Data TypePython Data Typeobjectdict,classarraylist,tuple,setstringstr,datetime,bytes,enumnumberint, float,enumboolboolnullNoneSide by sideStandard LibraryJsonBindSerializing a datetime to JSON is not possible by default:importjsonimportdatetimemydate=datetime.datetime.now().date()mydate=json.dumps(mydate)outputTypeError: Object of type date is not JSON serializableTo do it,  it is necessary to create an  Encoder:importjsonimportdatetimeclassDateTimeEncoder(json.JSONEncoder):defdefault(self,obj):ifisinstance(obj,(datetime.datetime,datetime.date,datetime.time)):returnobj.isoformat()elifisinstance(obj,datetime.timedelta):return(datetime.datetime.min+obj).time().isoformat()returnsuper(DateTimeEncoder,self).default(obj)mydate=datetime.datetime.now().date()encoder=DateTimeEncoder()encoder.encode(mydate)Output:"2023-12-19"However, this only works converting from python to json.
To read values from json to python it is necessary to write an additional Decoder class.By default datetime values are fully supported by JsonBind:import jsonbind as jb 
import datetime
mydate = datetime.datetime.now().date()
mydate = jb.dumps(mydate)
print(mydate)
mynewdate = jb.loads('"2023-12-20"', cls=datetime)
print(mynewdate)Output:"2023-12-19"
"2023-12-20"Creating new bindings for python typesJsonBind allows the creation of new Bindings with very little code.In this example a new binding for the type datetime is created to encode to the object Json datatype (dict):importjsonbindasjbimportdatetimeclassMyDateBinding(jb.TypeBinding):def__init__(self):super().__init__(json_type=dict,python_type=datetime.datetime)defto_json_value(self,python_value:datetime.datetime)->dict:return{"year":python_value.year,"month":python_value.month,"day":python_value.day}defto_python_value(self,json_value:dict,python_type:type)->datetime.datetime:returndatetime.datetime(year=json_value["year"],month=json_value["month"],day=json_value["day"])jb.Bindings.set_binding(MyDateBinding())print(jb.dumps(datetime.datetime.now()))Output:{"year":2023,"month":12,"day":20}To convert a JSON value to date time using the new binding, we need the following code:new_date=jb.loads('{"year":2025,"month":10,"day":22}',cls=datetime.datetime)print(new_date,type(new_date))Output:2025-10-2200:00:00<class'datetime.datetime'>JsonBind automatically matches the expected type to the custom binding as there can only exist one binding per python
type. This means that in this code the default binding for datetime was replaced during the set_binding operation.Creating bound classesimportjsonbindasjbimportdatetimeclassMyClass(jb.BoundClass):def__init__(self):self.text="Hello World"self.date=datetime.datetime.now()self.data=[3,1,4,1,5,9,2]my_object=MyClass()print("Serialization test:")print(jb.dumps(my_object))new_object=jb.loads('{"text":"Deseralization test","date":"2023-12-23","data":[6,2,8,3,1,8,4]}',cls=MyClass)print()print("Deserialization test:")print("Text: ",new_object.text,new_object.text.__class__)print("Date: ",new_object.date,new_object.date.__class__)print("Data: ",new_object.data,new_object.data.__class__)Output:Serializationtest:{"text":"Hello World","date":"2023-12-20","data":[3,1,4,1,5,9,2]}Deserializationtest:Text:Deseralizationtest<class'str'>Date:2023-12-2300:00:00<class'datetime.datetime'>Data:[6,2,8,3,1,8,4]<class'list'>Standard Json load and dump functionsLoading a json string to its default python typeimportjsonbindasjbmydict=jb.loads('{"name":"German Espinosa","age":41,"weight":190.0}')print(mydict,type(mydict))mylist=jb.loads('[1, 2, 3, 4]')print(mylist,type(mylist))myint=jb.loads('1')print(myint,type(myint))myfloat=jb.loads('10.5')print(myfloat,type(myfloat))mystring=jb.loads('"Hello World"')print(mystring,type(mystring))mybool=jb.loads('true')print(mybool,type(mybool))output{'name': 'German Espinosa', 'age': 41, 'weight': 190.0} <class 'dict'>
[1, 2, 3, 4] <class 'list'>
1 <class 'int'>
10.5 <class 'float'>
Hello World <class 'str'>
True <class 'bool'>Serializing a json string from its default python typeimportjsonbindasjbmydict={"name":"German Espinosa","age":41,"weight":190.0}print(jb.dumps(mydict),type(mydict))mylist=[1,2,3,4]print(jb.dumps(mylist),type(mylist))myint=1print(jb.dumps(myint),type(myint))myfloat=10.5print(jb.dumps(myfloat),type(myfloat))mystring="Hello World"print(jb.dumps(mystring),type(mystring))mybool=Trueprint(jb.dumps(mybool),type(mybool))output{'name': 'German Espinosa', 'age': 41, 'weight': 190.0} <class 'dict'>
[1, 2, 3, 4] <class 'list'>
1 <class 'int'>
10.5 <class 'float'>
Hello World <class 'str'>
True <class 'bool'>Loading a json string to a non-default python typeimportjsonbindasjbmytuple=jb.loads('[1, 2, 3, 4]',cls=tuple)print(mytuple,type(mytuple))myset=jb.loads('[1, 2, 3, 4]',cls=set)print(myset,type(myset))mybytes=jb.loads('"SGVsbG8gV29ybGQ="',cls=bytes)print(mybytes,type(mybytes))importdatetimemydate=jb.loads('"2023-12-19"',cls=datetime.datetime)print(mydate,type(mydate))output(1, 2, 3, 4) <class 'tuple'>
{1, 2, 3, 4} <class 'set'>
b'Hello World' <class 'bytes'>
2023-12-19 00:00:00 <class 'datetime.datetime'>Serializing a json string from a non-default python typeimportjsonbindasjbmydict={"name":"German Espinosa","age":41,"weight":190.0}print(jb.dumps(mydict),type(mydict))mylist=[1,2,3,4]print(jb.dumps(mylist),type(mylist))myint=1print(jb.dumps(myint),type(myint))myfloat=10.5print(jb.dumps(myfloat),type(myfloat))mystring="Hello World"print(jb.dumps(mystring),type(mystring))mybool=Trueprint(jb.dumps(mybool),type(mybool))output{'name': 'German Espinosa', 'age': 41, 'weight': 190.0} <class 'dict'>
[1, 2, 3, 4] <class 'list'>
1 <class 'int'>
10.5 <class 'float'>
Hello World <class 'str'>
True <class 'bool'>JsonBind Object & ListJsonBind provides special implementations of Object and List datatypes that provide a lot of functionality to
interact with data in JSON format.Create your first json object:After installing the package, try the following python script:importjsonbindasjbmyobject=jb.Object(name="German Espinosa",age=41,weight=190.0)print("name:",myobject.name,type(myobject.name).__name__)print("age:",myobject.age,type(myobject.age).__name__)print("weight:",myobject.weight,type(myobject.weight).__name__)print(myobject)outputname: German Espinosa str
age: 41 int
weight: 190.0 float
{"name":"German Espinosa","age":41,"weight":190.0}Loading json_data:To quickly load json data into objects, use the load command:importjsonbindasjbmyobject=jb.Object.load("{\"name\":\"German Espinosa\",\"age\":41,\"weight\":190.0}")print("name:",myobject.name,type(myobject.name).__name__)print("age:",myobject.age,type(myobject.age).__name__)print("weight:",myobject.weight,type(myobject.weight).__name__)outputname: German Espinosa str
age: 41 int
weight: 190.0 floatFormatting outputs:You can easily format data, even in complex json hierarchical structures:importjsonbindasjbmyobject=jb.Object.parse("{\"name\":\"German Espinosa\",\"age\":41,\"weight\":190.0,\"place_of_birth\":{\"country\":\"Argentina\",\"city\":\"Buenos Aires\"}}")print(myobject.format("{name}was born in{place_of_birth.city},{place_of_birth.country}"))outputGerman Espinosa was born in Buenos Aires, ArgentinaWorking with pre-structured data:A powerful way to read and write json is to pre-define the structure of the data. This creates standarized data samples that are easire to be consumed by other tools.
To pre-define structure of a json object, you need to create your own custom class extending the JsonObject:importjsonbindasjbclassMyJsonClass(jb.Object):def__init__(self,name="",age=0,weight=0.0):self.name=nameself.age=ageself.weight=weightmyobject=MyJsonClass('German Espinosa',41,190.0)json_string=str(myobject)print(json_string)output{"name":"German Espinosa","age":41,"weight":190.0}Loading values into an existing object:You can also load values from a json string directly into an existing custom JsonObject:importjsonbindasjbclassMyJsonClass(jb.Object):def__init__(self,name="",age=0,weight=0.0):self.name=nameself.age=ageself.weight=weightmyobject=MyJsonClass('German Espinosa',41,190.0)myobject.parse("{\"name\":\"Benjamin Franklin\",\"age\":84,\"weight\":195.5}")json_string=str(myobject)print(json_string)output{"name":"Benjamin Franklin","age":84,"weight":195.5}Object to json conversion:All objects with type MyJsonClass will produce perfectly formed json when converted to string.
If you need to retrieve the json string representing the object:importjsonbindasjbclassMyJsonClass(jb.Object):def__init__(self,name="",age=0,weight=0.0):self.name=nameself.age=ageself.weight=weightmyobject=MyJsonClass('German Espinosa',41,190.0)json_string=str(myobject)print(json_string)output{"name":"German Espinosa","age":41,"weight":190.0}Json to object conversion:You can create instances of your json objects from strings containing a correct json representation:importjsonbindasjbclassMyJsonClass(jb.Object):def__init__(self,name="",age=0,weight=0.0):self.name=name# stringself.age=age# intself.weight=weight# floatjson_string="{\"name\":\"German Espinosa\",\"age\":41,\"weight\":190.0}"myobject=MyJsonClass.parse(json_string)print("name:",myobject.name,type(myobject.name).__name__)print("age:",myobject.age,type(myobject.age).__name__)print("weight:",myobject.weight,type(myobject.weight).__name__)outputname: German Espinosa str
age: 41 int
weight: 190.0 floatnote: all members are populated with the right values using the same data type declared in the default constructor of the classNested json structures:You can create complex structures with nested objects:importjsonbindasjbclassPerson(jb.Object):def__init__(self,name="",age=0):self.name=nameself.age=ageclassTransaction(jb.Object):def__init__(self,buyer=None,seller=None,product="",amount=0.0):self.buyer=buyerifbuyerelsePerson()self.seller=sellerifsellerelsePerson()self.product=productself.amount=amountmytransaction=Transaction(Person("German Espinosa",41),Person("Benjamin Franklin",84),"kite",150.5)print(mytransaction)output{"buyer":{"name":"German Espinosa","age":41},"seller":{"name":"Benjamin Franklin","age":84},"product":"kite","amount":150.5}Json lists:You can load full lists with values from a json string to a JsonList:importjsonbindasjbfibonacci=jb.List(list_type=int)json_string="[1,1,2,3,5,8,13,21]"fibonacci.parse(json_string)You can also load a list of json objects:importjsonbindasjbclassPerson(jb.Object):def__init__(self,name="",surname=""):self.name=nameself.surname=surnameperson_list=jb.List(list_type=Person)json_string="[{\"name\":\"german\",\"surname\":\"espinosa\"},{\"name\":\"benjamin\",\"surname\":\"franklin\"}]"person_list.parse(json_string)Lists can also be used as members of other objects:importjsonbindasjbclassPerson(jb.Object):def__init__(self):self.name=""self.surname=""self.languages=List(list_type=str)person=Person.parse("{\"name\":\"German\",\"surname\":\"Espinosa\",\"languages\":[\"english\",\"spanish\",\"portuguese\"]}")print(person)output{"name":"German","surname":"Espinosa","languages":["english","spanish","portuguese"]}