Morag
Morag

Reputation: 49

How do I implement a default serialization method for a custom class?

I'm attempting to write a program that uses json objects to communicate and am running into trouble with custom classes. Basically the object I pass into json.dumps is a large dictionary, mostly just using basic classes (strings, lists, and other dictionaries mostly) but in some cases I have to map a string to an object of custom class A.

When I use those objects, I get a message like:

TypeError: <module.A object at 0x01659110> is not JSON serializable

What I'd like to do is write a default encoding method for objects of type A. The objects are very simple and just contain a label (str type) and some various integers. The label is enough to identify A uniquely, so if json uses the label alone, that is fine.

After reading many similar problems online, I ended up with:

class AEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, A):
            return o.label
        else:
            return super(AEncoder, self).default(o)

The problem is, the sources I got that from all include a call like:

AEncoder().encode(object) 

This needs to be called before passing the object into json.dumps(), but I do not have access to the object beforehand. It is stashed away inside the large dictionary mentioned earlier, sometimes not accessible by me. I've also tried implementing A's __repr__ function but I get the same error.

So... to attempt a summarized version: How do I tell json.dumps() what to do with a custom class when I have no access to the specific object being passed into json.dumps()?

Please let me know if any clarification is needed.

Upvotes: 2

Views: 264

Answers (1)

jterrace
jterrace

Reputation: 67113

You pass the cls argument to the dump function:

json.dumps(obj, cls=AEncoder)

Here's an example usage:

>>> class Something(object):
...    def __init__(self, v):
...       self.v = v
... 
>>> import json
>>> class SEncoder(json.JSONEncoder):
...    def default(self, obj):
...       if isinstance(obj, Something):
...          return {'classtype': 'Something', 'v': obj.v}
...       return json.JSONEncoder.default(self, obj)
... 
>>> s1 = Something(3)
>>> s2 = Something(4)
>>> o = [s1, s2, 6, "hello"]
>>> print json.dumps(o, cls=SEncoder, indent=2)
[
  {
    "classtype": "Something", 
    "v": 3
  }, 
  {
    "classtype": "Something", 
    "v": 4
  }, 
  6, 
  "hello"
]

Upvotes: 1

Related Questions