将动态Python对象转换为JSON

76

我需要知道如何将一个动态的Python对象转换为JSON。这个对象必须能够拥有多级子对象。例如:

class C(): pass
class D(): pass

c = C()
c.dynProperty1 = "something"
c.dynProperty2 = { 1, 3, 5, 7, 9 }
c.d = D()
c.d.dynProperty3 = "d.something"

# ... convert c to json ...

我尝试了这段代码:

import json
 
class C(): pass
class D(): pass
 
c = C()
c.what = "now?"
c.now = "what?"
c.d = D()
c.d.what = "d.what"
 
json.dumps(c.__dict__)

但我收到了一个错误,错误提示说 TypeError: <__main__.D instance at 0x99237ec> is not JSON serializable

如何让任何作为类的子对象自动使用它们的__dict__进行序列化?


除了动态元素之外,我不知道在将对象序列化为json之前会添加哪些属性。 - Trevor
你也会注意到在你的情况下,重复的解决方案也是有效的。 - phihag
@phihag:感谢您指出这一点。这帮助我意识到我的问题比我想象的要更复杂(请参见更新后的问题)。 - Trevor
那么你可能应该提出一个新的问题。特别注意不要包含无效的示例代码。例如,你想要 class C(object): pass。我添加了一个答案,应该可以解决你的问题。 - phihag
首先,感谢您的回答。我认为那应该可以解决问题。但是,我有点困惑。我不明白为什么“class C(): pass”是无效的代码。我错过了什么吗?我对Python还比较新。 - Trevor
3
抱歉,我完全错了。class C(): pass 当然是有效的,但在Python 2.x中它会创建一个旧风格的类(就像class C: pass一样)。旧风格的类是奇怪的东西。通过从 object 继承,您可以获得更加合理的新风格行为。 - phihag
4个回答

143

指定default=参数(文档):

json.dumps(c, default=lambda o: o.__dict__)

7
我的一个对象属性是datetime,在使用时出现了“'AttributeError' object has no attribute 'dict'” 的错误。 - bachr
1
@arun 对于一个集合,你需要使用不同的方法。如果你期望同时处理对象和集合,可以使用一个辅助函数代替 lambda 表达式,测试 isinstance(o, set),然后返回类似 list(o) 的内容。 - phihag
1
这个比json.dumps(c.__dict__)更好,为什么? - soulmachine
6
@soulmachine的代码只是转储了一个字典,其值(以及递归地值的值)仍然可能是没有JSON表示的Python对象。这个答案中的代码对于所有这些有问题的对象都使用了__dict__,进行了递归处理。 - phihag
2
@soulmachine 来自 Python3 文档如果指定了 default 参数,那么它应该是一个函数,用于处理无法序列化的对象。它应该返回一个 JSON 可编码版本的对象或引发 TypeError 异常。如果未指定,则会引发 TypeError 异常。 - MarAja
显示剩余3条评论

16
json.dumps(c.__dict__)

如果这正是你想要的,那么这将给你一个通用的 JSON 对象。


2
在查看phihag的评论后,我进行了进一步的测试并意识到这种解决方案并不适用于所有情况...正在更新问题... - Trevor
我也可以这样做。 - fth

9
尝试使用这个包python-jsonpickle

这是一个Python库,可将任意对象图序列化为JSON。它可以接受几乎任何Python对象,并将对象转换为JSON。此外,它还可以将对象重新组合回Python。


0

json.dumps 期望参数为字典。例如,对于变量 c,属性 c.__dict__ 是一个将属性名映射到相应对象的字典。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接