C'est assez délicat, car namedtuple()
est une usine qui renvoie un nouveau type dérivé de tuple
. Une approche consisterait à faire en sorte que votre classe hérite également de UserDict.DictMixin
mais tuple.__getitem__
est déjà défini et attend un nombre entier indiquant la position de l'élément, et non le nom de son attribut :
>>> f = foobar('a', 1)
>>> f[0]
'a'
À la base, le namedtuple est étrangement adapté à JSON, puisqu'il s'agit en fait d'un fichier de type type personnalisé dont les noms de clés sont fixés dans le cadre de la définition du type contrairement à un dictionnaire où les noms des clés sont stockés dans l'instance. Cela vous empêche de "faire le tour" d'un namedtuple, c'est-à-dire que vous ne pouvez pas décoder un dictionnaire en un namedtuple sans une autre information, comme un marqueur de type spécifique à l'application dans le dict. {'a': 1, '#_type': 'foobar'}
ce qui est un peu compliqué.
Ce n'est pas idéal, mais si vous avez seulement besoin de coder Une autre approche consiste à étendre ou à modifier votre encodeur JSON pour qu'il tienne compte de ces types. Voici un exemple de sous-classement du codeur Python json.JSONEncoder
. Cela permet de s'assurer que les namedtuples imbriqués sont correctement convertis en dictionnaires :
from collections import namedtuple
from json import JSONEncoder
class MyEncoder(JSONEncoder):
def _iterencode(self, obj, markers=None):
if isinstance(obj, tuple) and hasattr(obj, '_asdict'):
gen = self._iterencode_dict(obj._asdict(), markers)
else:
gen = JSONEncoder._iterencode(self, obj, markers)
for chunk in gen:
yield chunk
class foobar(namedtuple('f', 'foo, bar')):
pass
enc = MyEncoder()
for obj in (foobar('a', 1), ('a', 1), {'outer': foobar('x', 'y')}):
print enc.encode(obj)
{"foo": "a", "bar": 1}
["a", 1]
{"outer": {"foo": "x", "bar": "y"}}
0 votes
Pour python 2.7 : stackoverflow.com/questions/16938456/