यह बहुत मुश्किल है, क्योंकि namedtuple()
एक कारखाना है जो एक नए प्रकार से प्राप्त होता है tuple
। एक दृष्टिकोण यह होगा कि आपकी कक्षा भी विरासत में मिली हो UserDict.DictMixin
, लेकिन tuple.__getitem__
पहले से ही एक पूर्णांक को परिभाषित करता है और यह अपेक्षा करता है कि तत्व की स्थिति को निरूपित किया जाए, न कि इसकी विशेषता का नाम:
>>> f = foobar('a', 1)
>>> f[0]
'a'
इसके दिल में नामित नाम JSON के लिए एक विषम फिट है, क्योंकि यह वास्तव में एक कस्टम-निर्मित प्रकार है जिसके प्रमुख नाम टाइप परिभाषा के हिस्से के रूप में तय किए गए हैं , एक शब्दकोश के विपरीत जहां प्रमुख नाम उदाहरण के अंदर संग्रहीत होते हैं। यह आपको नामांकित नाम के "राउंड-ट्रिपिंग" से रोकता है, उदाहरण के लिए, आप डिक्शनरी में किसी अन्य जानकारी के बिना किसी नाम-पत्र में वापस शब्दकोश में डिकोड नहीं कर सकते हैं, जैसे कि एक ऐप-विशिष्ट प्रकार का मार्कर {'a': 1, '#_type': 'foobar'}
, जो कि थोड़ा सा हैकी है।
यह आदर्श नहीं है, लेकिन अगर आपको केवल नामांकितों को शब्दकोशों में सांकेतिक शब्दों में बदलना चाहिए , तो एक अन्य दृष्टिकोण इन प्रकारों को विशेष मामले में अपने JSON एनकोडर को विस्तारित या संशोधित करना है। यहाँ पायथन को उपवर्गित करने का एक उदाहरण दिया गया है 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"}}