亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用Python> = 2.7將嵌套的namedtuple序列化為JSON

使用Python> = 2.7將嵌套的namedtuple序列化為JSON

繁花不似錦 2021-03-19 14:15:06
我有一個類似于CalvinKrishy的問題 Samplebias的解決方案無法使用我擁有的數據。我正在使用Python 2.7。數據如下:元組>>> a_t = namedtuple('a','f1 words')>>> word_t = namedtuple('word','f2 value')>>> w1 = word_t(f2=[0,1,2], value='abc')>>> w2 = word_t(f2=[3,4], value='def')>>> a1 = a_t(f1=[0,1,2,3,4],words=[w1, w2])>>> a1a(f1=[0, 1, 2, 3, 4], words=[word(f2=[0, 1, 2], value='abc'), word(f2=[3, 4], value='def')])辭典>>> w3 = {}>>> w3['f2'] = [0,1,2]>>> w3['value'] = 'abc'>>> w4 = {}>>> w4['f2'] = [3,4]>>> w4['value'] = 'def'>>> a2 = {}>>> a2['f1'] = [0, 1, 2, 3, 4]>>> a2['words'] = [w3,w4]>>> a2{'f1': [0, 1, 2, 3, 4], 'words': [{'f2': [0, 1, 2], 'value': 'abc'}, {'f2': [3, 4], 'value': 'def'}]}如您所見,a1和a2都相同,除了一個命名為tuple,另一個是dict。但是json.dumps是不同的:>>> json.dumps(a1._asdict())'{"f1": [0, 1, 2, 3, 4], "words": [[[0, 1, 2], "abc"], [[3, 4], "def"]]}'>>> json.dumps(a2)'{"f1": [0, 1, 2, 3, 4], "words": [{"f2": [0, 1, 2], "value": "abc"}, {"f2": [3, 4], "value": "def"}]}'我想要a1的json格式完全像對a2所做的那樣。
查看完整描述

2 回答

?
PIPIONE

TA貢獻1829條經驗 獲得超9個贊

問題出在使用namedtuple._asdict,而不是json.dumps。如果您一起看代碼,namedtuple(..., verbose=True)將會看到以下內容:


def _asdict(self):

    'Return a new OrderedDict which maps field names to their values'

    return OrderedDict(zip(self._fields, self))

實際上,只有頂層被更改為OrderedDict,所有包含的元素都保持不變。這意味著嵌套的namedtuples仍然是tuple子類,并且(正確地)進行了序列化等等。


如果可以接受對特定轉換函數的調用(如對的調用_asdict),則可以編寫自己的函數。


def namedtuple_asdict(obj):

  if hasattr(obj, "_asdict"): # detect namedtuple

    return OrderedDict(zip(obj._fields, (namedtuple_asdict(item) for item in obj)))

  elif isinstance(obj, basestring): # iterables - strings

     return obj

  elif hasattr(obj, "keys"): # iterables - mapping

     return OrderedDict(zip(obj.keys(), (namedtuple_asdict(item) for item in obj.values())))

  elif hasattr(obj, "__iter__"): # iterables - sequence

     return type(obj)((namedtuple_asdict(item) for item in obj))

  else: # non-iterable cannot contain namedtuples

    return obj


json.dumps(namedtuple_asdict(a1))

# prints '{"f1": [0, 1, 2, 3, 4], "words": [{"f2": [0, 1, 2], "value": "abc"}, {"f2": [3, 4], "value": "def"}]}'

如您所見,最大的問題是嵌套結構不是 namedtuples而是可以包含它們。


查看完整回答
反對 回復 2021-03-30
?
DIEA

TA貢獻1820條經驗 獲得超3個贊

這是我使用的版本,改編自宮城先生的版本。我使用isinstancewithcollections.abc代替hasattr,然后_type在結果字典中將一個鍵命名為namedtuple類的名稱。


import collections.abc


def _nt_to_dict(obj):

    recurse = lambda x: map(_nt_to_dict, x)

    obj_is = lambda x: isinstance(obj, x)

    if obj_is(tuple) and hasattr(obj, '_fields'):  # namedtuple

        fields = zip(obj._fields, recurse(obj))

        class_name = obj.__class__.__name__

        return dict(fields, **{'_type': class_name})

    elif obj_is(collections.abc.Mapping):

        return type(obj)(zip(obj.keys(), recurse(obj.values())))

    elif obj_is(collections.abc.Iterable) and not obj_is(str):

        return type(obj)(recurse(obj))

    else:

        return obj


查看完整回答
反對 回復 2021-03-30
  • 2 回答
  • 0 關注
  • 203 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號