namedtuple()
에서 파생 된 새로운 유형을 반환하는 팩토리 이기 때문에 이것은 매우 까다 롭습니다 tuple
. 한 가지 방법은 클래스도에서 상속하도록하는 UserDict.DictMixin
것이지만 tuple.__getitem__
이미 정의되어 있으며 속성 이름이 아닌 요소의 위치를 나타내는 정수를 예상합니다.
>>> f = foobar('a', 1)
>>> f[0]
'a'
기본적으로 namedtuple은 키 이름이 인스턴스 내부에 저장되는 사전과 달리 키 이름이 유형 정의의 일부로 고정 되는 사용자 지정 빌드 유형 이므로 JSON에 이상하게 맞습니다 . 이렇게하면 명명 된 튜플을 "왕복"하는 것을 방지 할 수 있습니다. 예를 들어 dict의 앱 특정 유형 마커와 같은 다른 정보 없이는 사전을 명명 된 튜플로 다시 디코딩 할 수 없습니다 {'a': 1, '#_type': 'foobar'}
.
이것은 이상적이지는 않지만 명명 된 튜플을 사전 으로 인코딩하기 만하면되는 경우 다른 접근 방식은 JSON 인코더를 이러한 유형의 특수한 경우로 확장하거나 수정하는 것입니다. 다음은 Python을 서브 클래 싱하는 예입니다 json.JSONEncoder
. 이렇게하면 중첩 된 명명 된 튜플이 사전으로 제대로 변환되는지 확인하는 문제가 해결됩니다.
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"}}