Serialize my class as JSON causes "__init__() got an unexpected keyword argument 'indent'" ?

Peter Otten __peter__ at web.de
Sat Dec 18 05:30:13 EST 2010


shearichard wrote:

> Hi - I've got a straightforward class I want to serialize as JSON
> (actually I want to a serialize a list of them but I believe that's
> irrelevant).
> 
> I've subclassed JSONEncoder and defined my own version of the
> 'default' method ( based upon what I read at
> http://docs.python.org/library/json.html ) but when I then try to
> serialize the class I get the (fairly weird) error message : "TypeError:
> __init__() got an unexpected keyword argument 'indent'".
> 
> I suspect I'm doing something pretty fundamentally wrong but I don't
> know what - can anyone tell me what's wrong (or alternatively tell me
> how to log this as a bug ;-)
> 
> Here's my test case :
> 
> import json
> class SuperPeople(object):
>     pass
> class People(SuperPeople, json.JSONEncoder):
>     def __init__(self, name, age):
>         self.__name = name
>         self.__age = age
>     def default(self, obj):
>         if isinstance(obj, People):
>             return [obj.__name, obj.__age]
>         else:
>             return json.JSONEncoder.default(self, obj)
> 
> def main():
>     lstPeople = []
>     lstPeople.append(People("Mary", 50))
>     lstPeople.append(People("Joe", 40))
>     lstPeople.append(People("Sue", 30))
> 
>     print json.dumps(lstPeople, cls=People)
> 
> 
> if __name__ == "__main__":
>     main()
> 
> 
> ... and this is what the stacktrace looks like  ....
> 
> Traceback (most recent call last):
>   File "testJSON.py", line 24, in <module>
>     main()
>   File "testJSON.py", line 20, in main
>     json.dumps(lstPeople, cls=People)
>   File "C:\bin\installed\Python2.6\lib\json\__init__.py", line 237, in
> dumps
>     **kw).encode(obj)
> TypeError: __init__() got an unexpected keyword argument 'indent'
> 
> 
> ... I'm running Python 2.6 on Win32.
> 
> All suggestions welcomed .

You pass the encoder *class* to json.dumps(), so the function has to 
instantiate it. It does that with the arguments that an encoder class must 
accept. There's no way for it to expect that an encoder requires a name and 
an age.

The solution is to separate the encoder and the class that shall be encoded. 
Here's one way:

import json

class People(object):
    def __init__(self, name, age):
        self.__name = name
        self.__age = age
    def get_json_state(self):
        return [self.__name, self.__age]

class PeopleEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, People):
            return obj.get_json_state()
        else:
            return json.JSONEncoder.default(self, obj)

def main():
    lstPeople = []
    lstPeople.append(People("Mary", 50))
    lstPeople.append(People("Joe", 40))
    lstPeople.append(People("Sue", 30))

    print json.dumps(lstPeople, cls=PeopleEncoder)


if __name__ == "__main__":
    main()





More information about the Python-list mailing list