1

When I try to use json.dumps on an object of a class that uses __slots__, I get "...is not JSON serializable," or possibly an AttributeError that __dict__ is missing. How can I get this to work? It seems that __slots__ should tell the interpreter to use a virtual dictionary for compatibility.

import json

class Foo:
     __slots__ = ["bar"]
     def __init__(self):
         self.bar = 0

json.dumps(Foo())
David Ehrmann
  • 7,366
  • 2
  • 31
  • 40
  • 4
    You cannot do this on objects *without* `__slots__` either. What makes you think it would work on other objects? – Martijn Pieters Aug 27 '14 at 18:51
  • 2
    You might find the question [_Making object JSON serializable with regular encoder_](http://stackoverflow.com/questions/18478287/making-object-json-serializable-with-regular-encoder) helpful. – martineau Aug 27 '14 at 19:02
  • You need to use `pickle` if you want to serialize an object. – Vor Aug 27 '14 at 19:38
  • @MartijnPieters: It looks like I was *actually* doing `json.dumps(Foo(), default=lambda o: o.__dict__)`, but I forgot that when writing my question. – David Ehrmann Aug 27 '14 at 19:39
  • @Vor: I need a serialization that will work outside Python and is human-readable. `pickle` won't work outside Python, and even has issues within Python if class definitions change. – David Ehrmann Aug 27 '14 at 19:41
  • @Vor: no, pickle is but one option. JSON just takes some more work. – Martijn Pieters Aug 27 '14 at 20:38

1 Answers1

3

Plain, vanilla json.dumps() doesn't support custom classes, period. It doesn't matter if they use __slots__ or not here.

A popular way to handle custom classes is to use a hook that returns their __dict__ attribute instead, and that obviously won't work here. You'd have to find another way to serialise such objects.

One way would be for such objects to have a dedicated method:

class Foo:
     __slots__ = ["bar"]
     def __init__(self):
         self.bar = 0

     def json_serialize(self):
         return {'bar': self.bar}

and use that in your default hook:

json.dumps(Foo(), default=lambda o: o.json_serialize())
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343