簡體   English   中英

使用jsonpickle進行類型演變(python)

[英]type evolution with jsonpickle (python)

jsonpickle中對此有任何支持嗎?

例如,我存儲並反對,他們修改其架構,然后嘗試將其加載回去。

例如,以下更改(屬性添加)

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'

jsonpickle中不支持類型演變或類型遷移。

最好的做法是將數據的JSON表示(通過json.loads )加載到列表/字典/字符串/數字的基本Python結構中。 遍歷此Python表示形式,添加空/默認b鍵。 然后通過json.dumps重新保存JSON。

然后,您可以使用jsonpickle加載數據的修改版本。

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

如果對象模型更復雜,這顯然會變得更加復雜,但是您可以檢查py / object鍵以查看是否需要修改對象。

由於版本問題,僅jsonpickle不足以持久化對象。 您還需要在JSON輸出中保留版本標識符,以便在讀取舊版本時可以對數據進行改造(清理)。

話雖如此,您可以做一些事情來使生活更輕松。 您可以將json.dumps的default = dict參數與iter結合使用。 這將使您可以將對象持久保存為字典。 然后,當您閱讀它時,可以使用** dict運算符和關鍵字參數從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__ ctor中運行初始化代碼。 這將變成:

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'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM