首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用jsonpickle (python)的类型演变

使用jsonpickle (python)的类型演变
EN

Stack Overflow用户
提问于 2012-10-26 19:15:47
回答 2查看 1.2K关注 0票数 1

在jsonpickle中有对此的支持吗?

例如,我存储和对象,它们修改它的模式,然后尝试将它加载回来。

下面的更改,例如,(属性添加)

代码语言:javascript
复制
import jsonpickle

class Stam(object):

   def __init__(self, a):
     self.a = a

   def __str__(self):
     return '%s with a=%s' % (self.__class__.__name__, str(self.a))


js = jsonpickle.encode(Stam(123))
print 'encoded:', js

class Stam(object):

   def __init__(self, a, b):
     self.a = a
     self.b = b

   def __str__(self):
     return '%s with a=%s, b=%s' % (self.__class__.__name__, str(self.a), str(self.b))

s=jsonpickle.decode(js)
print 'decoded:', s

生成一个错误:

代码语言:javascript
复制
encoded: {"py/object": "__main__.Stam", "a": 123}
decoded: Traceback (most recent call last):
  File "C:\gae\google\appengine\ext\admin\__init__.py", line 317, in post
    exec(compiled_code, globals())
  File "<string>", line 25, in <module>
  File "<string>", line 22, in __str__
AttributeError: 'Stam' object has no attribute 'b'
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-27 08:48:41

在jsonpickle中不支持类型演化或类型迁移。

最好的做法是(通过json.loads)将数据的JSON表示加载到由列表/字典/字符串/数字组成的基本Python结构中。遍历这个Python表示,添加空的/默认的b键。然后通过json.dumps重新保存JSON。

然后,可以使用jsonpickle加载修改后的数据版本。

代码语言:javascript
复制
temp = json.loads(js)
temp['b'] = None
js = json.dumps(temp)
jsonpickle.decode(js)

如果您的对象模型更复杂,这显然会变得更加复杂,但您可以检查py/object键来查看是否需要修改对象。

票数 1
EN

Stack Overflow用户

发布于 2016-01-27 08:28:07

由于版本控制问题,单独的jsonpickle不足以持久化对象。您还需要在JSON输出中保留一个版本标识符,以便在读取旧版本时可以对数据进行翻新(清理)。

也就是说,你可以做一些事情来让生活变得更容易。可以在对象上将json.dumps的default=dict参数与iter结合使用。这将允许您将对象持久化为字典。然后,当您读取它时,您可以使用**dict运算符和关键字参数来重新实例化JSON字典中的对象。

这允许您读入持久化对象,并为任何新属性提供初始化。例如,如果我们从一个具有val1属性的类开始并持久化它,然后扩展该类以拥有val2属性,并从持久化状态恢复if:

代码语言:javascript
复制
import json

class Stam( object ) :
    val1 = None
    def __init__( self, val1=None ) :
        self.val1 = val1

    def __iter__( self ) : return {
        'val1':self.val1
    }.iteritems()

obj1 = Stam( val1='a' )
persisted = json.dumps( obj1, default=dict )

class Stam( object ) :
    val1 = None
    val2 = None
    def __init__( self, val1=None, val2='b' ) :
        self.val1 = val1
        self.val2 = val2

    def __iter__( self ) : return {
        'val1':self.val1,
        'val2':self.val2
    }.iteritems()

obj2 = json.loads( persisted, object_hook=lambda d: Stam(**d) )
assert obj2.val1 == 'a'
assert obj2.val2 == 'b'

当然,我们也可以使用jsonpickle并跳过__iter__和额外的json参数,因为jsonpickle会忽略缺少的属性。因此,任何新的val2都会提供静态类初始化,但它不会在__init__ ctor中运行初始化代码。这将变成:

代码语言:javascript
复制
import jsonpickle

class Stam( object ) :
    val1 = None
    def __init__( self, val1 ) :
        self.val1 = val1

obj1 = Stam( 'a' )
persisted = jsonpickle.encode( obj1 )

class Stam( object ) :
    val1 = None
    val2 = 'b'
    def __init__( self, val1, val2 ) :
        self.val1 = val1
        self.val2 = val2

obj2 = jsonpickle.decode( persisted )
assert obj2.val1 == 'a'
assert obj2.val2 == 'b'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13085911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档