12

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])
>>> a1
a(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 は、一方がnamedtupleで、もう一方が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"}]}'

a2の場合とまったく同じように、a1のjson形式が必要です。

4

2 に答える 2

12

問題は、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"}]}'

ご覧のとおり、最大の問題は、 s ではなく、それらを含むことができるネストされた構造を持つこと namedtupleです。

于 2015-09-25T13:06:40.620 に答える