Custom JSON Encoder with python

The json package can encode python objects as strings with the json.JSONEncoder class, and decodes strings into python objects using the json.JSONDecoder class.

Here is an example :

import json

# Convert a dict to a string
json.dumps({"name": "Paul", "age": 24})

# Convert a string to a dict
json.loads('{"name": "Paul", "age": 24}')

By default, these class supports dict, list, tuple, str, int, float, bool and None values. But it’s possible to overload JsonEncoder and JsonDecoder to support Datetime, Decimal or any of your classes.

It can be useful when you want to serialize or deserialize objects. I like to use it when I store mongodb queries (which are json objects) as a string in database.

Let’s start with json encoding.

# extend the json.JSONEncoder class
class JSONEncoder(json.JSONEncoder):

# overload method default
def default(self, obj):

# Match all the types you want to handle in your converter
if isinstance(obj, datetime):
return arrow.get(obj).isoformat()
# Call the default method for other types
return json.JSONEncoder.default(self, obj)

In the above example, we convert datetime objects to isoformat string.

We can also convert Decimal or any other object

elif isinstance(obj, Decimal):
return float(Decimal(obj).quantize(Decimal("0.01"), ROUND_UP))
elif isinstance(obj, MyClass):
return JSONEncoder().encode({
"value1": obj.value_1,
"value2": obj.value_2
})

And let’s do the opposite with JSONDecoder. It’s a little bit different here, we have to pass a method to object_hook in the constructor. We will implement our custom deserializations conditions in this method.

class JSONDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)

def object_hook(self, obj):

# handle your custom classes
if isinstance(obj, dict):
if "value1" in obj and "value2" in obj:
print(obj)
return MyClass(obj.get("value_1"), obj.get("value_2"))

# handling the resolution of nested objects
if isinstance(obj, dict):
for key in list(obj):
obj[key] = self.object_hook(obj[key])

return obj

if isinstance(obj, list):
for i in range(0, len(obj)):
obj[i] = self.object_hook(obj[i])

return obj

# resolving simple strings objects
# dates
if isinstance(obj, str):
obj = self._extract_date(obj)

return obj

We can add two shortcuts for a more readable code.

def json_encode(data):
return JSONEncoder().encode(data)
def json_decode(string):
return JSONDecoder().decode(string)

And use it this way

from JsonEncoder import json_encode, json_decodemy_obj = MyClass("value1", "value2")
json_encode(my_obj)
my_str = '{"name": "Paul", "birthdate": "1992-02-22T00:00:00+00:00", "int_number": 122}'
json_decode(my_str)

You can find all the code, with examples on Github : JsonEncoder.

If you want like to read more about the json package, you can refer to the documentation.

--

--

--

I work at yper. I’m a python developer, learning data science. I’ve made a www.blindfoldchesstactic.com app

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Javascript Consoles are fun, beautiful and have great potential. You should know how to use it!

Hi.123

Learning Flowtype

Be Aware Of Your GitHub Actions Workflow With Slack

Cheat Sheet: A Full-Stack Project in Docker

String Literals in JavaScript: Should I Use Double-quotes or Single-quotes?

Unique Number of Occurrences Problem

A high-level overview of JS engines and Webassembly

Credit: https://dev.to/edisonpappi/how-javascript-engines-chrome-v8-works-50if

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alexis Gomes

Alexis Gomes

I work at yper. I’m a python developer, learning data science. I’ve made a www.blindfoldchesstactic.com app

More from Medium

How to hide you API key with Python

Python Experiment: For VS Comprehension 1

What is SQLAlchemy?

GraphQL with Python — Part-2