与jsonpickle键入演进(蟒)(type evolution with jsonpickle

2019-10-17 08:37发布

是否有任何jsonpickle支持的呢?

例如:I存储和对象,他们修改它的架构,然后尝试加载回来。

下面的变化,例如,(属性加成)

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

产生一个错误:

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'

Answer 1:

没有为jsonpickle内进化型或类型迁移的支持。

你最好的行动方针是先装载(通过json.loads数据的JSON表示)到列表/类型的字典/字符串/数字的基本的Python结构。 遍历这个Python的表示中,在空/默认添加b键。 然后重新保存通过JSON json.dumps

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

temp = json.loads(js)
temp['b'] = None
js = json.dumps(temp)
jsonpickle.decode(js)

这显然变得更加复杂,如果你的对象模型是比较复杂的,但你可以检查PY /目标关键看是否需要修改的对象。



Answer 2:

由于版本问题,独自jsonpickle不是保持对象足够。 您还需要保持一个版本标识符在JSON输出,这样就可以改造(清理)当你正在阅读的是旧版本的数据。

随着中说,有出头你可以做,使生活更轻松。 你可以用你的对象ITER使用json.dumps默认=字典参数结合。 这将让你坚持你的对象作为字典。 然后,当你在你读它可以使用**字典运营商和关键字参数从JSON字典重新实例化对象。

这使您可以读取你的持久对象和供应初始化对任何新的属性。 例如,如果我们开始与具有VAL1属性的类,并坚持它,然后展开类有val2的属性,如果从持久状态恢复:

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__构造函数。 这将成为:

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'


文章来源: type evolution with jsonpickle (python)