使用 jsonpickle 从文件中保存和加载对象

Posted

技术标签:

【中文标题】使用 jsonpickle 从文件中保存和加载对象【英文标题】:saving and loading objects from file using jsonpickle 【发布时间】:2011-01-24 18:43:26 【问题描述】:

我有以下使用 jsonpickle 将 python 对象写入文件的简单方法:

def json_serialize(obj, filename, use_jsonpickle=True):
    f = open(filename, 'w')
    if use_jsonpickle:
        import jsonpickle
        json_obj = jsonpickle.encode(obj)
        f.write(json_obj)
    else:
        simplejson.dump(obj, f) 
    f.close()

def json_load_file(filename, use_jsonpickle=True):
    f = open(filename)
    if use_jsonpickle:
        import jsonpickle
        json_str = f.read()
        obj = jsonpickle.decode(json_str)
    else:
        obj = simplejson.load(f)
    return obj

问题是,每当我使用这些时,它会将我的对象作为字典加载回来(具有如下字段:“py/object”:“my_module.MyClassName”),而不是作为所使用类型的实际 Python 对象生成 json 字符串。如何让 jsonpickle 实际上将加载的字符串转换回对象?

为了说明这一点,请考虑以下几点:

class Foo:
    def __init__(self, hello):
    self.hello = hello

# make a Foo obj
obj = Foo("hello world")
obj_str = jsonpickle.encode(obj)
restored_obj = jsonpickle.decode(obj_str)
list_objects = [restored_obj]
# We now get a list with a dictionary, rather than
# a list containing a Foo object
print "list_objects: ", list_objects

这会产生:

list_objects:  ['py/object': 'as_events.Foo', 'hello': 'hello world']

而不是类似:[Foo()]。我该如何解决这个问题?

谢谢。

【问题讨论】:

你能在jsonpickle.decode() 行之前import as_events 吗? FWIW 这是一个很好的例子,说明何时应该使用with open() 上下文管理器进行文件写入。当你在这里序列化时遇到错误,你会让你的文件保持打开状态——这很糟糕。 【参考方案1】:

截至本文发布时,如果序列化对象是内部类,则存在一个导致编码错误的错误。确保该类不在另一个类中。我已经向维护者提出了问题。 https://github.com/jsonpickle/jsonpickle/issues/210

【讨论】:

【参考方案2】:

正确的答案是我没有从object 继承。如果没有从object 继承,jsonpickle 似乎无法正确解码在构造函数中采用一个或多个参数的类。我绝不是专家,但在类声明中使用Foo(object): 而不是Foo: 来修复它。

【讨论】:

【参考方案3】:

确保use_jsonpickle == Truejson_load_file() 中。您似乎使用jsonpickle 进行序列化并使用json 加载。

>>> import jsonpickle
>>> class A(object):
...    def __init__(self, name):
...       self.name = name
... 
>>> js = jsonpickle.encode(A('abc'))
>>> js
'"py/object": "__main__.A", "name": "abc"'     # <-- json string
>>> a = jsonpickle.decode(js)
>>> a
<__main__.A object at 0x7f826a87bd90>            # <-- python object
>>> a.name
u'abc'
>>> import json
>>> b = json.loads(js)
>>> b
u'py/object': u'__main__.A', u'name': u'abc'    # <-- dictionary

确保对象类型可用

>>> del A
>>> c = jsonpickle.decode(js)                  # no type available
>>> c
u'py/object': u'__main__.A', u'name': u'abc'
>>> type(c)
<type 'dict'>
>>> class A(object):
...    def __init__(self, name):
...        self.name = name
... 
>>> d = jsonpickle.decode(js)                   # type is available
>>> d
<__main__.A object at 0x7f826a87bdd0>
>>> type(d)
<class '__main__.A'>

【讨论】:

谁能告诉我 u'py/object': u'main.A', u'name': u'abc 中的这个“u”是什么' ? @ed22 它是how unicode string literals are written in Python 2。 repr(unicode_string) 使用相同的文本表示。 非常感谢!

以上是关于使用 jsonpickle 从文件中保存和加载对象的主要内容,如果未能解决你的问题,请参考以下文章

python3教程:jsonpickle和sqlite3持久化存储字典对象

python序列化与反序列化(jsonpickle)

python3教程:jsonpickle和sqlite3持久化存储字典对象

Python—序列化和反序列化模块(jsonpickle和shelve)

Python:使用jsonpickle无法两次或多次打印同一个对象。

从文件中重复写入和加载对象的 ArrayList