Inyoung Kim 김인영
Inyoung Kim 김인영

Reputation: 1586

JSON Serialize a dict with a nested custom object

There were other questions asking how to serialize a object of a custom class. But the answers were specific to only dumping the object alone. I, instead want to dump a dictionary that has the custom class object as a value. I want to use the json.dump method

example_dict_format = {
    "name_A": [message0, message1, ...],
    "name_B": [message0, ...], ...
}

class Message:
    def __init__(self, time, message):
        self.time = time
        self.message = message

    def toJSON(self):
        return json.dump(self.__dict__)

    def __repr__(self):
        return self.toJson()

The custom class is not that complex, it is simple enough to represent as just a dictionary. I tried adding __repr__ and toJSON methods to the class, did not work. I got the following error

raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Message is not JSON serializable

Question: How do you dump such dictionary?

Upvotes: 0

Views: 1473

Answers (2)

shoap
shoap

Reputation: 11

user2099394 answer is correct, but if you want to keep the code as part of the class you are trying to encode, then you could do it via brute force:

class Message:
    def __init__(self, time, message):
        self.time = time
        self.message = message

    def toJson(self):
        d = {}
        d["time"] = str(self.time)
        d["message"] = self.message
        return json.dumps(d)

Upvotes: 1

StefanMZ
StefanMZ

Reputation: 473

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Message):
            obj_dict = {key: str(obj.__dict__[key]) for key in obj.__dict__}
            return obj_dict
        # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, obj)

json.dump(result, fp, cls=ComplexEncoder, indent=4)

Upvotes: 1

Related Questions