2012-10-26 62 views
1

在jsonpickle中有沒有這方面的支持?類型演變與jsonpickle(蟒蛇)

E.g.我存儲和對象,他們修改它的架構,然後嘗試加載它。

以下變化,例如,(屬性添加)

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' 

回答

1

沒有爲jsonpickle內型進化或類型遷移沒有支撐。

您的最佳行動方式是將數據的JSON表示加載到列表/字典/字符串/數字的基本Python結構中(通過json.loads)。遍歷這個Python表示,添加空的/默認的b鍵。然後通過json.dumps重新保存JSON。

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

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

這顯然變得更爲複雜,如果你的對象模型是比較複雜的,但你可以檢查PY /目標關鍵看是否需要修改的對象。

0

由於版本控制問題,單獨使用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都會提供靜態類初始化 ,但它不會運行在初始化代碼中的初始化代碼。這將變成:

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'