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

S

shearichard

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 .

Richard.
 
P

Peter Otten

shearichard said:
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()
 
S

shearichard

shearichard said:
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()

Brilliant - thank you very much.

Now that you've explained it I can see why the documentation is
written the way it is ! Before I saw your example I thought the
documentation was a bit strange but I can see now what it was trying
to tell me !

Your help is much appreciated.

Richard.
 
T

Terry Reedy

Brilliant - thank you very much.

Now that you've explained it I can see why the documentation is
written the way it is ! Before I saw your example I thought the
documentation was a bit strange but I can see now what it was trying
to tell me !

If you have any idea who to improve that part of the doc so you would
have understood it without Peter's nice explanation and example here,
please open a doc issue on the tracker.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top