Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python serialize objects list to JSON

Tags:

python

json

I am trying to serialize to JSON the __dict__ of an object, which is working fine, until I append objects to one of the instance attribute of my first object:

from json import dumps

class A(object):
    def __init__(self):
        self.b_list = []

class B(object):
    def __init__(self):
        self.x = 'X'
        self.y = 'Y'
    def __repr__(self):
        return dumps(self.__dict__)

a = A()

print dumps(a.__dict__)  # works fine

a.b_list.append(B())

print dumps(a.__dict__)

When calling for the second time dumps, I got the following TypeError:

TypeError: {"y": "Y", "x": "X"} is not JSON serializable

I don't understand why I keep getting this error while I can't see why this is not serializable to JSON.

like image 444
evuez Avatar asked Nov 19 '13 18:11

evuez


People also ask

How do you serialize an object to JSON in Python?

Use toJSON() Method to make class JSON serializable So we don't need to write custom JSONEncoder. This new toJSON() serializer method will return the JSON representation of the Object. i.e., It will convert custom Python Object to JSON string.

How do you serialize a JSON list in Python?

Use json. dumps() to serialize a list into a JSON object. Use json. dumps(list) to serialize list into a JSON string.

How do you write a list of objects to a JSON file in Python?

You can convert any Python object to a JSON string and write JSON to File using json. dumps() function and file. write() function respectively.

What Python objects are JSON serializable?

The JSON encoder implemented in the dump() and dumps() methods can serialize only a few basic object types. These are dictionaries, lists, strings, integers, floats, Booleans, and None.


1 Answers

That's because instances of B are not a simple type. Because you gave B a __repr__ method, the instance is printed as it's JSON representation, but it is not itself a supported JSON type.

Remove the __repr__ method and the traceback is much less confusing:

>>> class A(object):
...     def __init__(self):
...         self.b_list = []
... 
>>> class B(object):
...     def __init__(self):
...         self.x = 'X'
...         self.y = 'Y'
... 
>>> a = A()
>>> a.b_list.append(B())
>>> 
>>> print dumps(a.__dict__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <__main__.B object at 0x10a753e10> is not JSON serializable

Use the default keyword argument to encode custom objects:

def encode_b(obj):
    if isinstance(obj, B):
        return obj.__dict__
    return obj

json.dumps(a, default=encode_b)

Demo:

>>> def encode_b(obj):
...     if isinstance(obj, B):
...         return obj.__dict__
...     return obj
... 
>>> dumps(a.__dict__, default=encode_b)
'{"b_list": [{"y": "Y", "x": "X"}]}'
like image 175
Martijn Pieters Avatar answered Oct 22 '22 22:10

Martijn Pieters