简体   繁体   中英

Prevent JSON serialization from throwing an exception in Python

What is a good way to prevent the python's json library from throwing an exception when it encounters objects that it does not know how to serialize?

We are using json to serialize dict objects, sometimes properties of the objects are not recognized by the json library, causing it to throw an exception. Instead of throwing an exception, it would be nice if it just skipped over that property of the dict instead. It could set the property value to "None" or even a message: "Cannot serialize".

Right now, the only way I know how to do this is to explicitly identify and skip over each data type that json might encounter that will make it throw an exception. As you can see, I have it turning datetime objects into strings, but also skipping over some geo-point objects from the shapely library:

import json
import datetime
from shapely.geometry.polygon import Polygon
from shapely.geometry.point import Point
from shapely.geometry.linestring import LineString

# This sublcass of json.JSONEncoder takes objects from the
# business layer of the application and encodes them properly
# in JSON.
class Custom_JSONEncoder(json.JSONEncoder):

    # Override the default method of the JSONEncoder class to:
    # - format datetimes using strftime('%Y-%m-%d %I:%M%p')
    # - de-Pickle any Pickled objects
    # - or just forward this call to the superclass if it is not
    #   a special case object
    def default(self, object, **kwargs):
        if isinstance(object, datetime.datetime):
            # Use the appropriate format for datetime
            return object.strftime('%Y-%m-%d %I:%M%p')
        elif isinstance(object, Polygon):
            return {}
        elif isinstance(object, Point):
            return {}
        elif isinstance(object, Point):
            return {}
        elif isinstance(object, LineString):
            return {}

        return super(Custom_JSONEncoder, self).default(object)

This should do what you want. You can add special cases before the catch-all return, or customize the fallback value.

import json
import datetime


class Custom_JSONEncoder(json.JSONEncoder):
    def default(self, obj, **kwargs):
        if isinstance(obj, datetime.datetime):
            # Use the appropriate format for datetime
            return obj.strftime('%Y-%m-%d %I:%M%p')
        return None

You could omit the call to the json.JSONEncoder.default() if you don't want to raise TypeError. default() is only called for objects that json doesn't know how to serialize.

I think this would be good:

class Rectangle(object):
    def to_json(self):
        return {}

class Custom_JSONEncoder(json.JSONEncoder):
    def default(self,  obj, **kwargs):
        if hasattr(obj, 'to_json'):
            return obj.to_json()
        ...

You will need to add methods to the other classes but for me this is fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM