Bif*_*iff 7 python serialization json python-3.x
鉴于下面的代码示例,如何使用Python 3使用JSON序列化这些类实例?
class TreeNode():
def __init__(self, name):
self.name = name
self.children = []
Run Code Online (Sandbox Code Playgroud)
当我尝试做一个时,json.dumps
我收到以下错误:
TypeError: <TreeNode object at 0x7f6sf4276f60> is not JSON serializable
然后我才能发现,如果我将默认值设置json.dumps
为返回,__dict__
我可以将其序列化很好,但后来做了json.loads
一个问题.
我可以找到许多带有基本字符串的自定义编码器/解码器示例,但是没有列表,在这种情况下是self.children.子列表将保存子节点及其子节点的其他节点.我需要一种方法来获得所有这些.
由于您要处理树结构,因此使用嵌套字典是很自然的。下面的代码片段创建了的子类,dict
并将其用作__dict__
实例的基础-这是我在许多不同环境中遇到的有趣且有用的技巧:
返回匿名类或对象以用作“结构”是否更可取?
(Stackoverflow)
jsobject.py
(PyDoc.net)
制作类似于Javascript对象的Python对象
(James Robert的博客)
AttrDict
(ActiveState配方)
具有属性样式访问权限的字典
(ActiveState配方)
...事实上,我经常认为这是一个(鲜为人知的)Python成语。
class TreeNode(dict):
def __init__(self, name, children=None):
super().__init__()
self.__dict__ = self
self.name = name
self.children = [] if not children else children
Run Code Online (Sandbox Code Playgroud)
这解决了一半的序列化工作,但是当读取产生的数据时json.loads()
,它将是一个常规的字典对象,而不是的实例TreeNode
。这是因为JSONEncoder
可以对字典(及其子类)本身进行编码。
解决该问题的一种方法是,向TreeNode
该类添加替代构造函数方法,可以调用该方法从json.loads()
返回的嵌套字典中重建数据结构。
这就是我的意思:
@staticmethod
def from_dict(dict_):
""" Recursively (re)construct TreeNode-based tree from dictionary. """
root = TreeNode(dict_['name'], dict_['children'])
root.children = list(map(TreeNode.from_dict, root.children))
return root
if __name__ == '__main__':
import json
tree = TreeNode('Parent')
tree.children.append(TreeNode('Child 1'))
child2 = TreeNode('Child 2')
tree.children.append(child2)
child2.children.append(TreeNode('Grand Kid'))
child2.children[0].children.append(TreeNode('Great Grand Kid'))
json_str = json.dumps(tree, sort_keys=True, indent=2)
print(json_str)
print()
pyobj = TreeNode.from_dict(json.loads(json_str)) # reconstitute
print('pyobj class: {}'.format(pyobj.__class__.__name__)) # -> TreeNode
print(json.dumps(pyobj, sort_keys=True, indent=2))
Run Code Online (Sandbox Code Playgroud)
输出:
class TreeNode(dict):
def __init__(self, name, children=None):
super().__init__()
self.__dict__ = self
self.name = name
self.children = [] if not children else children
Run Code Online (Sandbox Code Playgroud)