The world’s leading publication for data science, AI, and ML professionals.

Single Line of Code to Interchange Between Python Objects and JSON

The easiest way to serialise/deserialise between Python objects and JSON – Attr and Cattr

Photo by geralt on Pixabay
Photo by geralt on Pixabay

Python Programming Tips

In one of my previous articles, I have introduced probably the best practice of Object-Oriented Programming (OOP) in Python, which is using the library "Attrs".

Probably the Best Practice of Object-Oriented Python – Attr

However, in most cases, we use OOP is probably due to it can be serialised into strings such as JSON strings. More conveniently, we should also be able to deserialise it back to class instances for other purposes.

For example, one of the most popular usages of these is Data Access Objects (DAO). So, we may implement CRUD functions with the objects to seamlessly integrate with the persistence layer.

Therefore, most of the time, we might want to serialise the Python objects into JSON for transferring purposes. Reversely, we also want to deserialise JSON strings into Python objects if we’re using Python to receive the data as JSON types.

In this article, I’ll introduce another library – "Cattr" which can be used together with "Attr". I’ll focus on "Cattr", so if you are interesting what are the capabilities that "Attr" has, please check out the article above mentioned.

Installation and Importing

Photo by JoshuaWoroniecki on Pixabay
Photo by JoshuaWoroniecki on Pixabay

First of all, we need to install these two libraries using pip.

pip install attrs
pip install cattrs

In this article, all we need from attr are the annotations for the class and the attribute function, so let’s import them together with the library cattr.

from attr import attrs, attrib
import cattr

Basic Usage of Cattr

Photo by Free-Photos on Pixabay
Photo by Free-Photos on Pixabay

Basically, cattr is used for converting the data objects between structured and unstructured states. For example, instances from classes are considered structured data, whereas Python dictionaries and JSON objects are considered unstructured data.

Suppose we want to regulate data in a list with uncertain, we can use cattr as follows.

from typing import Tuple
cattr.structure([1.01, True, False, "2", "I will be ignored"], Tuple[int, int, int, int])

Please note that we are using the type alias "Tuple" from the typing library, which is built-in to Python 3. If you are not sure what it is, here is the official documentation.

typing – Support for type hints – Python 3.8.3 documentation

In this example, the float, boolean and string objects are regulated into integers as specified in the template. Also, the 5th object in the list has been ignored because there are only 4 elements in the template.

Cattr Works with Attr

Photo by PublicDomainPictures on Pixabay
Photo by PublicDomainPictures on Pixabay

cattr works best with attr when dealing with classes.

Suppose we define the class as follows.

@attrs
class Person:
  name = attrib()
  age = attrib()
def tell_age(self):
    print(f'My name is {self.name} and my age is {self.age}.')

Of course, as introduced in my previous article, attr can be used for serialising the instances into dictionaries.

from attr import asdict
p1 = Person('Chris', 32)
asdict(p1)

Of course, cattr can do this as well.

cattr.unstructure(p1)

It looks like the asdict() function from attr is more intuitive. However, this is just serialisation. What if we got a dictionary and want to deserialise it into a Person object? This time attr cannot help, but we can use cattr.

p2 = cattr.structure({'name': 'Chelsea', 'age': 1}, Person)

Cattr Works with a List of Dictionaries

Photo by josephredfield on Pixabay
Photo by josephredfield on Pixabay

The above example is only deserialising a single dictionary. In practice, that’s not ideal. What if we want to deserialise a list of dictionaries into Python objects? In the example below, we have three dictionaries to be deserialised in a list.

p_list_raw = [
  {'name': 'Alice', 'age': 20},
  {'name': 'Bob', 'age': 25},
  {'name': 'Chris', 'age': 32}
]

To implement this, we will need to define a "template", too. Please note that the argument we passed in is not a "Person" anymore, but a list of "Person" objects. Therefore, we will need to use the typing alias again.

from typing import List
p_list = cattr.structure(p_list_raw, List[Person])

Therefore, we got a list of person objects from the list of person dictionaries.

Cattr Works with JSON

Photo by SCY on Pixabay
Photo by SCY on Pixabay

Of course, we are not satisfied by only serialise/deserialise to Python dictionaries. We want it to be a JSON object! It is also very easy. In fact, the only thing we need to do is to import the json library which is also a Python built-in module.

Recall that we have a list of Python objects p_list from the previous example.

To serialise it into a JSON array, simply use cattr together with json.dumps() function as follows.

import json
json_obj = json.dumps(cattr.unstructure(p_list))
print(json_obj)

To deserialise the JSON array into a list of Python objects is also very easy. Simple use the json.loads() function in conjunction with cattr.

p_list = cattr.structure(json.loads(json_obj), List[Person])

Just don’t forget we need the typing alias "List" as the template.

The above example also showed that the deserialised objects can be called with their class functions, of course 🙂

Summary

Photo by geralt on Pixabay
Photo by geralt on Pixabay

In this article, I have introduced how to use cattr together with attr libraries to achieve Python objects serialising into dictionaries/JSON, as well as dictionaries and JSON objects deserialising into Python objects in an extremely easy way.

Given that this is usually not an easy job in most of the other programming languages, at least not that fast to be implemented, I would say that it reflects why people love Python in a single aspect.

All the code in this article can be found here:

Attrs+Cattrs.ipynb

Join Medium with my referral link – Christopher Tao

If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)


Related Articles