I’m writing in python some json encoders for a dictionary derived class, the class EPPI_dictDB, the object of this class may be store as value some instances of the class parser.
BUT when I would encode something goes wrong and the instance of the class EPPI_dictDB passed to the specific encoder function becomes an instance of the class parser!
Let me explain better with an example.
If I execute this code
import json
import raw.data_input as data_input
p = data_input.parser()
class data():
def __str__(self):
return self.name
data1 = data()
data1.name = "data1"
data1.proteins = ['acc1','acc2']
data1.peptides = [('acc1',['SEQTWO']),
('acc2',['SEQONE'])]
p.parse(data1)
s = EPPI_dbopen('tmp.prj', flag='n')
s["parser"] = p
print s.__class__
print isinstance(s, EPPI_DictDB)
print isinstance(s, data_input.parser)
I obtain these results:
<class '__main__.EPPI_DictDB'>
True
False
after I call the encoder:
print json.dumps(obj=s, cls=projectEncoder)
Inside the code of the encode I put some ‘prints’ to determine the nature of the passed object:
class projectEncoder(json.JSONEncoder):
def default(self, obj):
print obj.__class__
print isinstance(obj, EPPI_DictDB)
print isinstance(obj, data_input.parser)
if isinstance(obj, EPPI_DictDB):
result = obj.__dict__
if "parser" in result.keys():
pars = result["parser"]
result["parser"] = parserEncoder().encode(pars)
if "selected" in results.keys():
sel = result["selected"]
result["selected"] = parserEncoder().encode(sel)
return result
return json.JSONEncoder.default(self, obj)
The results of inner prints are:
<class 'raw.data_input.parser'>
False
True
Could anyone explain me what happen?
Guessing a bit:
JSON encoders already know how to handle dicts, so it treats your dict subclass the same way as a dict. However, when it reaches s[“parser”], it doesn’t know what to do with the object, so it calls your
defaultmethod on it. I.e. from your code, it’s seeingp, nots.This seems to be what the docs say.
EDIT
Looking at what you’re actually doing, I think there should be an easier way to achieve this:
If the
"selected"field is another type, then just change the second line to: