递归地将python对象图转换为字典

2024-04-27 04:54:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图把数据从一个简单的对象图转换成一个字典。我不需要类型信息或方法,也不需要再将其转换回对象。

我找到了this question about creating a dictionary from an object's fields,但它不是递归的。

作为python的新手,我担心我的解决方案可能很难看,或者不符合python,或者以某种模糊的方式被破坏,或者只是简单的旧NIH。

我的第一次尝试似乎是成功的,直到我尝试使用列表和字典,而且似乎更容易检查传递的对象是否有一个内部字典,如果没有,则将其作为一个值(而不是执行所有的isinstance检查)。我以前的尝试也没有重新出现在对象列表中:

def todict(obj):
    if hasattr(obj, "__iter__"):
        return [todict(v) for v in obj]
    elif hasattr(obj, "__dict__"):
        return dict([(key, todict(value)) 
            for key, value in obj.__dict__.iteritems() 
            if not callable(value) and not key.startswith('_')])
    else:
        return obj

这似乎工作得更好,不需要例外,但我仍然不确定这里是否有案例,我不知道它落在哪里。

如有任何建议,将不胜感激。


Tags: 对象keyinobj列表forreturnif
3条回答

递归地将对象转换为JSON的一行代码。

import json

def get_json(object):
  return json.loads(
    json.dumps(object, default=lambda o: getattr(o, '__dict__', str(o)))
  )

object = SomeClass()
print("Json = ", get_json(object))

我自己的尝试和从Anurag Uniyal和Lennart Regebro的答案中得到的线索的结合对我最有效:

def todict(obj, classkey=None):
    if isinstance(obj, dict):
        data = {}
        for (k, v) in obj.items():
            data[k] = todict(v, classkey)
        return data
    elif hasattr(obj, "_ast"):
        return todict(obj._ast())
    elif hasattr(obj, "__iter__") and not isinstance(obj, str):
        return [todict(v, classkey) for v in obj]
    elif hasattr(obj, "__dict__"):
        data = dict([(key, todict(value, classkey)) 
            for key, value in obj.__dict__.items() 
            if not callable(value) and not key.startswith('_')])
        if classkey is not None and hasattr(obj, "__class__"):
            data[classkey] = obj.__class__.__name__
        return data
    else:
        return obj

我不知道检查basestring或object的目的是什么?另外,除非您有指向此类可调用项的属性,否则dict将不包含任何可调用项,但在这种情况下,这不是object的一部分吗?

因此,不要检查各种类型和值,而是让todict转换对象,如果它引发异常,则使用原始值。

只有当obj没有dict时,todict才会引发异常 e、 g

class A(object):
    def __init__(self):
        self.a1 = 1

class B(object):
    def __init__(self):
        self.b1 = 1
        self.b2 = 2
        self.o1 = A()

    def func1(self):
        pass

def todict(obj):
    data = {}
    for key, value in obj.__dict__.iteritems():
        try:
            data[key] = todict(value)
        except AttributeError:
            data[key] = value
    return data

b = B()
print todict(b)

它打印{'b1':1,'b2':2,'o1':{'a1':1} 可能还有其他一些情况需要考虑,但这可能是一个好的开始

特殊情况 如果一个对象使用插槽,那么您将无法获得dict例如

class A(object):
    __slots__ = ["a1"]
    def __init__(self):
        self.a1 = 1

插槽情况的修复方法可以是使用dir(),而不是直接使用dict

相关问题 更多 >