2011-09-20 92 views
3

我在python中编写了一些json编码器,用于字典派生类,类EPPI_dictDB,此类的对象可能会存储为值类解析器的一些实例。对象不匹配

但是当我编码出错的时候,传递给特定编码器函数的类EPPI_dictDB的实例成为类解析器的一个实例!

让我通过一个例子来更好地解释。 如果我执行这个代码

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) 

我得到这些结果:

<class '__main__.EPPI_DictDB'> 
True 
False 

后,我打电话编码器:

print json.dumps(obj=s, cls=projectEncoder) 

编码的代码里面我把一些“打印”确定通过对象的性质:

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) 

内打印的结果是:

<class 'raw.data_input.parser'> 
False 
True 

任何人都可以解释我发生什么事?

回答

0

猜测一下:

JSON编码器已经知道如何处理类型的字典,所以它把你的字典子类的方式作为一个字典一样。但是,当它到达s [“parser”]时,它不知道该如何处理该对象,因此它会调用您的default方法。即从你的代码,它看到p,而不是s

这似乎是什么the docs说。在你实际上在做什么

编辑

看,我觉得应该有实现这个更简单的方法:

def default(self, obj): 
    if isinstance(obj, data_input.parser): 
     return parserEncoder().encode(obj) 
    return super(projectEncoder, self).default(obj) 

如果"selected"领域是另一种类型,那么就改变第二行为:

if isinstance(obj, (data_input.parser, type_of_selected)): 
+0

这个问题不在编码器类中,而是在内建的'__dict__'中。我做了一个实验来确定这一点,我编写了从字典转换的函数,获得了我发布的相同结果。但我明白你的意思,你的信息很清楚,托马斯K,为什么我必须转换为字典?这个假设是错误的! – gunzapper

+0

@gunzapper:看起来很奇怪。但大概是如果你继承了字典,你使用了某种映射,并且只有一种方法可以用JSON来表示映射。事实上,看看你在做什么,应该有一个更简单的方法来做到这一点。我会编辑我的答案。 –

+0

昨天我选择了更简单的方法:在EPPI_DictDB中注册每个parser对象。我还编写了getty方法来获取解析器对象。有用。选择是解析器的派生类。但是,我认为这是一种奇怪的行为。我也会尝试你的解决方案。 – gunzapper