JSON ऑब्जेक्ट में आइटम "json.dumps" का उपयोग करके ऑर्डर से बाहर हैं?


157

मैं का उपयोग कर रहा हूँ json.dumpsजैसे में बदलने के लिए json

countries.append({"id":row.id,"name":row.name,"timezone":row.timezone})
print json.dumps(countries)

परिणाम मेरे पास है:

[
   {"timezone": 4, "id": 1, "name": "Mauritius"}, 
   {"timezone": 2, "id": 2, "name": "France"}, 
   {"timezone": 1, "id": 3, "name": "England"}, 
   {"timezone": -4, "id": 4, "name": "USA"}
]

मैं निम्नलिखित क्रम में चाबी रखना चाहता हूं: आईडी, नाम, टाइमज़ोन - लेकिन इसके बजाय मेरे पास टाइमज़ोन, आईडी, नाम है।

मुझे इसे कैसे ठीक करना चाहिए?

जवाबों:


244

दोनों पायथन dict(पायथन 3.7 से पहले) और JSON ऑब्जेक्ट अनियोजित संग्रह हैं। sort_keysकुंजी को सॉर्ट करने के लिए आप पैरामीटर पारित कर सकते हैं :

>>> import json
>>> json.dumps({'a': 1, 'b': 2})
'{"b": 2, "a": 1}'
>>> json.dumps({'a': 1, 'b': 2}, sort_keys=True)
'{"a": 1, "b": 2}'

यदि आपको किसी विशेष आदेश की आवश्यकता है; आप उपयोगcollections.OrderedDict कर सकते हैं :

>>> from collections import OrderedDict
>>> json.dumps(OrderedDict([("a", 1), ("b", 2)]))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict([("b", 2), ("a", 1)]))
'{"b": 2, "a": 1}'

पायथन 3.6 के बाद से , कीवर्ड तर्क क्रम संरक्षित है और ऊपर एक अच्छे सिंटैक्स का उपयोग करके फिर से लिखा जा सकता है:

>>> json.dumps(OrderedDict(a=1, b=2))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict(b=2, a=1))
'{"b": 2, "a": 1}'

PEP 468 देखें - खोजशब्द तर्क आदेश का संरक्षण

यदि आपका इनपुट JSON के रूप में दिया गया है तो ऑर्डर को सुरक्षित रखने के लिए (पाने के लिए OrderedDict), आप पास कर सकते हैं object_pair_hook, जैसा कि @Fred Yowsowski द्वारा सुझाया गया है :

>>> json.loads('{"a": 1, "b": 2}', object_pairs_hook=OrderedDict)
OrderedDict([('a', 1), ('b', 2)])
>>> json.loads('{"b": 2, "a": 1}', object_pairs_hook=OrderedDict)
OrderedDict([('b', 2), ('a', 1)])

2
ऑर्डरडिट के इनिट वास्तव में बदसूरत
जीन

3
@jean: प्रारंभिक मूल्य के साथ कोई संबंध नहीं है OrderedDict(), तो आप एक पारित कर सकते हैं dictकरने के लिए OrderedDict(), आप करने का आदेश दिया जोड़ों की सूची पारित कर सकते हैं dict()भी - हालांकि आदेश इन दोनों मामलों में खो जाता है।
jfs

मेरा आशय यह है कि आदेश को संरक्षित करते समय, कई टाइप करने की जरूरत है '(' और ')'
जीन

@jean: वहाँ ordereddict_literalsसे codetransformerपैकेज (अल्फा गुणवत्ता)
JFS

25
इसके अलावा, यदि आप JSON का उपयोग कर लोड करते हैं d = json.load(f, object_pairs_hook=OrderedDict), तो बाद json.dump(d)में मूल तत्वों के क्रम को बनाए रखेगा।
फ्रेड यांकोवस्की

21

जैसा कि दूसरों ने उल्लेख किया है कि अंतर्निहित तानाशाही अव्यवस्थित है। हालाँकि अजगर में ऑर्डरडाइट ऑब्जेक्ट हैं। (वे हाल के अजगर में निर्मित हैं, या आप इसका उपयोग कर सकते हैं: http://code.activestate.com/recipes/576693/ )।

मेरा मानना ​​है कि नए अजगर जोंस कार्यान्वयन सही ढंग से ऑर्डरडेडिकट्स में निर्मित को संभालते हैं, लेकिन मुझे यकीन नहीं है (और मेरे पास परीक्षण के लिए आसान पहुंच नहीं है)।

पुराने अजगर simplejson कार्यान्वयन न ऑर्डर किए गए ऑब्जेक्ट को अच्छी तरह से संभालते हैं .. और उन्हें आउटपुट करने से पहले नियमित रूप से dicts में कनवर्ट करते हैं .. लेकिन आप निम्न कार्य करके इसे दूर कर सकते हैं:

class OrderedJsonEncoder( simplejson.JSONEncoder ):
   def encode(self,o):
      if isinstance(o,OrderedDict.OrderedDict):
         return "{" + ",".join( [ self.encode(k)+":"+self.encode(v) for (k,v) in o.iteritems() ] ) + "}"
      else:
         return simplejson.JSONEncoder.encode(self, o)

अब इसके उपयोग से हमें यह मिलता है:

>>> import OrderedDict
>>> unordered={"id":123,"name":"a_name","timezone":"tz"}
>>> ordered = OrderedDict.OrderedDict( [("id",123), ("name","a_name"), ("timezone","tz")] )
>>> e = OrderedJsonEncoder()
>>> print e.encode( unordered )
{"timezone": "tz", "id": 123, "name": "a_name"}
>>> print e.encode( ordered )
{"id":123,"name":"a_name","timezone":"tz"}

जो बहुत ज्यादा वांछित है।

एक अन्य विकल्प यह होगा कि एनकोडर को सीधे आपके पंक्ति वर्ग का उपयोग करने के लिए प्रेरित किया जाए, और फिर आपको किसी मध्यवर्ती मध्यवर्ती या अनऑर्डिनेटड डिक्टेट की आवश्यकता नहीं होगी।


5
ध्यान दें कि JSON ऑब्जेक्ट्स अभी भी अनियंत्रित हैं ; एक JSON क्लाइंट ऑब्जेक्ट की परिभाषा पढ़ सकता है और पूरी तरह से कुंजियों के क्रम को अनदेखा कर सकता है और पूरी तरह से RFC अनुरूप हो सकता है।
मार्टिन पीटर्स

4
मार्टिज़न सही है, यह RFC अनुपालन को प्रभावित नहीं करता है, लेकिन यह निश्चित रूप से मूल्यवान हो सकता है यदि आप अपने JSON के लिए एक सुसंगत प्रारूप रखना चाहते हैं (उदाहरण के लिए यदि फ़ाइल संस्करण नियंत्रण में है, या मानव पाठक के लिए इसे आसान बनाना है। समझ, एंट्री ऑर्डर करने के लिए अपने दस्तावेज़ से मेल खाएं।)
माइकल एंडरसन

3
जो मामले में आप सिर्फ सेट sort_keysकरने के लिए Trueजब बुला json.dumps(); ऑर्डर स्थिरता के लिए (परीक्षण के लिए, स्थिर कैशिंग या वीसीएस कमिट करता है), सॉर्टिंग कुंजी पर्याप्त है।
मार्टिन पीटर्स

7

एक डिक्शनरी के ऑर्डर का उस ऑर्डर से कोई संबंध नहीं है, जो इसमें परिभाषित किया गया था। यह सभी डिक्शनरी का सच है, न कि सिर्फ JSON में बदल गया।

>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}

वास्तव में, शब्दकोश "उल्टा" होने से पहले ही बदल गया था json.dumps:

>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}

6

हे मुझे पता है कि यह इस उत्तर के लिए बहुत देर हो चुकी है, लेकिन Sort_keys जोड़ें और इसे इस प्रकार प्रस्तुत करें:

json.dumps({'****': ***},sort_keys=False)

यह मेरे लिए काम किया


4

json.dump () आपके शब्दकोश के अध्यापक को संरक्षित करेगा। फ़ाइल को टेक्स्ट एडिटर में खोलें और आप देखेंगे। यह आदेश की परवाह किए बिना कि क्या आप इसे एक आदेश भेजेंगे।

लेकिन json.load () सहेजे गए ऑब्जेक्ट के ऑर्डर को खो देगा, जब तक कि आप इसे ऑर्डरडेड डिक्ट () में लोड करने के लिए नहीं कहते हैं, जो ऑब्जेक्ट के साथ किया जाता है।

अन्यथा यह आदेश खो देगा क्योंकि सामान्य ऑपरेशन के तहत, यह सहेजे गए शब्दकोश ऑब्जेक्ट को एक नियमित रूप से लोड करता है और एक नियमित रूप से दिए गए आइटम के ओडर को संरक्षित नहीं करता है।


यह वास्तव में एक बेहतर फिक्स है क्योंकि लोड पर ऑर्डर बनाए रखने से डंप समय ऑर्डरिंग का ध्यान रखा जाता है। इस उत्तर के लिए धन्यवाद।
अरुण आर।

2

JSON में, जावास्क्रिप्ट के रूप में, ऑब्जेक्ट कुंजियों का क्रम व्यर्थ है, इसलिए यह वास्तव में कोई फर्क नहीं पड़ता कि वे किस क्रम में प्रदर्शित होते हैं, यह एक ही वस्तु है।


(और यह भी एक मानक पायथन के लिए सच है dict)

12
लेकिन जब से JSON एक स्ट्रिंग प्रतिनिधित्व है, जब तक कि इसे पार्स नहीं किया गया है, स्ट्रिंग तुलना (जैसे सिद्धांत) में अभी भी आदेश की आवश्यकता हो सकती है। इसलिए मैं यह नहीं कहूंगा कि यह कभी मायने नहीं रखता।
माइकल स्कॉट कथबर्ट

1
हालांकि यह जावास्क्रिप्ट (ECMA स्क्रिप्ट) मानक के लिए सही है, सभी कार्यान्वयन स्रोत क्रम में (स्ट्रिंग) कुंजी रखते हैं।
thebjorn

1
@Paulpro वास्तव में? कौनसा? मुझे पता है कि क्रोम ने एक बार यहां मानक का पालन करने की कोशिश की थी, लेकिन उसे सबमिट किया गया था ( code.google.com/p/v8/issues/detail?id=164 )। मुझे नहीं लगा कि उसके बाद भी कोई ऐसा ही प्रयास करेगा ...
thebjorn

2
@paulpro आप ओपी के सवाल को सही ढंग से संबोधित कर रहे हैं। मैं जोड़ना चाहता हूं, हालांकि, संरक्षण आदेश के लिए वैध उपयोग हैं। उदाहरण के लिए, कोई स्क्रिप्ट लिख सकता है जो JSON पढ़ता है, कुछ परिवर्तन लागू करता है, और परिणाम वापस लिखता है। आप ऑर्डर को संरक्षित रखना चाहते हैं ताकि एक अलग उपकरण स्पष्ट रूप से बदलाव दिखा सके।
पॉल रेडीमकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.