<p>这里有一个替代的答案,基本上是Python 3版本的my <a href="https://stackoverflow.com/a/18561055/355230">answer</a>对问题<a href="https://stackoverflow.com/questions/18478287/making-object-json-serializable-with-regular-encoder">Making object JSON serializable with regular encoder</a>的回答,这个问题可以pickle常规的<code>json</code>编码器尚未处理的任何Python对象。</p>
<p>有一些不同。其一,它不会对<code>json</code>模块进行monkey修补,因为这不是解决方案的基本部分。另一个是,尽管这次<code>TreeNode</code>类<em>不是从<code>dict</code>类派生的</em>,但它的功能基本上是相同的。这样做是为了防止stock<code>JSONEncoder</code>对其进行编码,并导致使用<code>JSONEncoder</code>子类中的<code>_default()</code>方法。</p>
<p>除此之外,它是一种非常通用的方法,并且能够处理许多其他类型的Python对象,包括用户定义的类,而无需修改。</p>
<pre><code>import base64
from collections import MutableMapping
import json
import pickle
class PythonObjectEncoder(json.JSONEncoder):
def default(self, obj):
return {'_python_object':
base64.b64encode(pickle.dumps(obj)).decode('utf-8') }
def as_python_object(dct):
if '_python_object' in dct:
return pickle.loads(base64.b64decode(dct['_python_object']))
return dct
# based on AttrDict -- https://code.activestate.com/recipes/576972-attrdict
class TreeNode(MutableMapping):
""" dict-like object whose contents can be accessed as attributes. """
def __init__(self, name, children=None):
self.name = name
self.children = list(children) if children is not None else []
def __getitem__(self, key):
return self.__getattribute__(key)
def __setitem__(self, key, val):
self.__setattr__(key, val)
def __delitem__(self, key):
self.__delattr__(key)
def __iter__(self):
return iter(self.__dict__)
def __len__(self):
return len(self.__dict__)
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, cls=PythonObjectEncoder, indent=4)
print('json_str:', json_str)
pyobj = json.loads(json_str, object_hook=as_python_object)
print(type(pyobj))
</code></pre>
<p>输出:</p>
<pre class="lang-none prettyprint-override"><code>json_str: {
"_python_object": "gANjX19tYWluX18KVHJlZU5vZGUKcQApgXEBfXECKFgIAAAAY2hp"
"bGRyZW5xA11xBChoACmBcQV9cQYoaANdcQdYBAAAAG5hbWVxCFgH"
"AAAAQ2hpbGQgMXEJdWJoACmBcQp9cQsoaANdcQxoACmBcQ19cQ4o"
"aANdcQ9oACmBcRB9cREoaANdcRJoCFgPAAAAR3JlYXQgR3JhbmQg"
"S2lkcRN1YmFoCFgJAAAAR3JhbmQgS2lkcRR1YmFoCFgHAAAAQ2hp"
"bGQgMnEVdWJlaAhYBgAAAFBhcmVudHEWdWIu"
}
<class '__main__.TreeNode'>
</code></pre>