Customizing JSON encoding

For class hinting, we'll provide three pieces of information. We'll include a __class__ key that names the target class. The __args__ key will provide a sequence of positional argument values. A __kw__ key will provide a dictionary of keyword argument values. (We will not use the __jsonclass__ key; it's too long and doesn't seem Pythonic.) This will cover all the options of __init__().

Here's an encoder that follows this design:

def blog_encode(object: Any) -> Dict[str, Any]:
if isinstance(object, datetime.datetime):
return dict(
__class__="datetime.datetime",
__args__=[],
__kw__=dict(
year=object.year,
month=object.month,
day=object.day,
hour=object.hour,
minute=object.minute,
second=object.second,
),
)
elif isinstance(object, Post):
return dict(
__class__="Post",
__args__=[],
__kw__=dict(
date=object.date,
title=object.title,
rst_text=object.rst_text,
tags=object.tags,
),
)
elif isinstance(object, Blog):
return dict(
__class__="Blog", __args__=[object.title, object.entries], __kw__={}
)
else:
return object

This function shows us two different flavors of object encodings for the three classes:

  • We encoded a datetime.datetime object as a dictionary of individual fields using keyword arguments.
  • We encoded a Post instance as a dictionary of individual fields, also using keyword arguments.
  • We encoded a Blog instance as a sequence of title and post entries using a sequence of positional arguments.

The else: clause is used for all other classes: this invokes the existing encoder's default encoding. This will handle the built-in classes. We can use this function to encode as follows:

text = json.dumps(travel, indent=4, default=blog_encode) 

We provided our function, blog_encode(), as the default= keyword parameter to the json.dumps() function. This function is used by the JSON encoder to determine the encoding for an object. This encoder leads to JSON objects that look like the following:

{ 
    "__args__": [ 
        "Travel", 
        [ 
            { 
                "__args__": [], 
                "__kw__": { 
                    "tags": [ 
                        "#RedRanger", 
                        "#Whitby42", 
                        "#ICW" 
                    ], 
                    "rst_text": "Some embarrassing revelation. Including u2639 and u2693ufe0e", 
                    "date": { 
                        "__args__": [], 
                        "__kw__": { 
                            "minute": 25, 
                            "hour": 17, 
                            "day": 14, 
                            "month": 11, 
                            "year": 2013, 
                            "second": 0 
                        }, 
                        "__class__": "datetime.datetime" 
                    }, 
                    "title": "Hard Aground" 
                }, 
                "__class__": "Post" 
            }, 
. 
. 
. 
    "__kw__": {}, 
    "__class__": "Blog" 
} 

We've taken out the second blog entry because the output was rather long. A Blog object is now wrapped with a dict that provides the class and two positional argument values. The Post and datetime objects, similarly, are wrapped with the class name and the keyword argument values.

Let's see how to customize JSON decoding.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset