क्या मुझे JSON को ऑर्डरडीड में लोड करने के लिए मिल सकता है?


427

ठीक है, तो मैं एक आज्ञापत्र का उपयोग कर सकता हूं json.dump। यही है, एक ऑर्डरडेन JSON के इनपुट के रूप में इस्तेमाल किया जा सकता है।

लेकिन क्या इसे आउटपुट के रूप में इस्तेमाल किया जा सकता है? यदि हां, तो कैसे? मेरे मामले में मैं loadएक आदेश में करना चाहते हैं ताकि मैं फ़ाइल में चाबियों का क्रम रख सकूं।

यदि नहीं, तो क्या किसी तरह का वर्कअराउंड है?


कभी भी आदेश को बनाए रखने की कोशिश नहीं की, हालांकि मैं निश्चित रूप से देख सकता हूं कि यह कैसे उपयोगी होगा।
fjtj

1
हां, मेरे मामले में मैं विभिन्न भाषाओं और अनुप्रयोगों के बीच की खाई को पाट रहा हूं, और JSON बहुत अच्छी तरह से काम करता है। लेकिन चाबियों का क्रम एक मुद्दा है। json.loadपाइथन में डायट्स के बजाय ऑर्डरेडडिक्ट्स का उपयोग करने के लिए एक सरल टिक करने के लिए बहुत बढ़िया होगा ।
c00kiemonster

3
JSON
अटकल

3
मुख्य आदेश किसी भी प्रकार की कार्यात्मक आवश्यकताओं के लिए नहीं है। यह मुख्य रूप से सिर्फ मानवीय पठनीयता के लिए है। अगर मैं सिर्फ इतना चाहता हूं कि मेरा जस सुंदर-छपा हुआ हो, तो मुझे किसी भी दस्तावेज़ के आदेश की बिल्कुल भी उम्मीद नहीं है।
अचार

5
यह भी बड़े अंतर से बचने में मदद करता है!
रिचर्ड रैस्ट

जवाबों:


609

हाँ तुम कर सकते हो। JSONDecoder को object_pairs_hookतर्क निर्दिष्ट करके । वास्तव में, यह प्रलेखन में दिया गया सटीक उदाहरण है।

>>> json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
OrderedDict([('foo', 1), ('bar', 2)])
>>> 

आप इस पैरामीटर को पास कर सकते हैं json.loads(यदि आपको अन्य उद्देश्यों के लिए डिकोडर उदाहरण की आवश्यकता नहीं है) तो:

>>> import json
>>> from collections import OrderedDict
>>> data = json.loads('{"foo":1, "bar": 2}', object_pairs_hook=OrderedDict)
>>> print json.dumps(data, indent=4)
{
    "foo": 1,
    "bar": 2
}
>>> 

उपयोग json.loadउसी तरह से किया जाता है:

>>> data = json.load(open('config.json'), object_pairs_hook=OrderedDict)

3
मैं हैरान हूं। डॉक्स का कहना है कि object_pairs_hook को प्रत्येक शाब्दिक के लिए बुलाया जाता है जो जोड़े में डिकोड हो जाता है। यह JSON में प्रत्येक रिकॉर्ड के लिए एक नया ऑर्डरडीक क्यों नहीं बनाता है?
टिम कीटिंग

3
हम्म ... डॉक्स कुछ अस्पष्ट रूप से वाक्यांशबद्ध हैं। उनका क्या मतलब है कि "सभी जोड़े को डिकोड करने का पूरा परिणाम", क्रम में, एक सूची के रूप में, object_pairs_hook"प्रत्येक जोड़ी को object_pairs_hook को पारित किया जाएगा" के रूप में पारित किया जाएगा,
SingleNegationElimation

लेकिन इनपुट जसन का मूल क्रम खो देता है?
SIslam

यह देखकर आश्चर्य हुआ कि json.loadइसे डिफ़ॉल्ट रूप से आदेशित नहीं किया गया है, लेकिन ऐसा लगता है कि यह केवल वही दिखा रहा है जो स्वयं जौन करता है - {}अनियंत्रित हैं, लेकिन []जौन में आदेश दिया गया है जैसा यहाँ
इलायची

1
@RandomCertainty हाँ, हर बार जब JSON ऑब्जेक्ट का स्रोत पार्सिंग करते समय सामने आता है, OrderedDictतो परिणामी अजगर मूल्य का निर्माण करने के लिए उपयोग किया जाएगा।
सिंगलएनजेशन इलेक्शन

125

पायथन 2.7+ के लिए सरल संस्करण

my_ordered_dict = json.loads(json_str, object_pairs_hook=collections.OrderedDict)

या अजगर 2.4 से 2.6 के लिए

import simplejson as json
import ordereddict

my_ordered_dict = json.loads(json_str, object_pairs_hook=ordereddict.OrderedDict)

4
आह, लेकिन इसमें object_pairs_hook को शामिल नहीं किया गया है - यही कारण है कि आपको अभी भी 2.6 में simplejson की आवश्यकता है। ;)
mjhm

8
यह नोट करना चाहते हैं simplejsonऔर ordereddictअलग-अलग पुस्तकालय हैं जिन्हें आपको स्थापित करने की आवश्यकता है।
फुन्हेहे

2
अजगर के लिए 2.7+: कोड में "आयात जसन, संग्रह" python2.6 के लिए- "एप्टीट्यूड इंस्टॉल पायथन-पाइप" और सिस्टम में "पाइप इंस्टॉल ऑर्डरडिक"
ZiTAL

यह JSONDecoder के साथ पिछले विधि की तुलना में बहुत आसान और तेज़ है।
नटिम

अजीब तरह से, पीपे में, शामिल जसन में विफल हो जाएगा loads('{}', object_pairs_hook=OrderedDict)
मैथ्यू Schinckel

37

कुछ बेहतरीन खबरें! संस्करण 3.6 के बाद से cPython कार्यान्वयन ने शब्दकोशों ( https://mail.python.org/pipermail/python-dev/2016-Sest/146327.html ) के सम्मिलन क्रम को संरक्षित रखा है । इसका मतलब यह है कि json पुस्तकालय अब डिफ़ॉल्ट रूप से संरक्षित करने का आदेश दे रहा है। अजगर 3.5 और 3.6 के बीच व्यवहार में अंतर को ध्यान से देखें। कोड:

import json
data = json.loads('{"foo":1, "bar":2, "fiddle":{"bar":2, "foo":1}}')
print(json.dumps(data, indent=4))

Py3.5 में परिणामी क्रम अपरिभाषित है:

{
    "fiddle": {
        "bar": 2,
        "foo": 1
    },
    "bar": 2,
    "foo": 1
}

अजगर अजगर के cPython कार्यान्वयन में 3.6:

{
    "foo": 1,
    "bar": 2,
    "fiddle": {
        "bar": 2,
        "foo": 1
    }
}

वास्तव में बड़ी खुशखबरी यह है कि यह पायथन 3.7 के रूप में एक भाषा विनिर्देश बन गया है (जैसा कि cPython 3.6+ के कार्यान्वयन विवरण के विपरीत है): https://mail.python.org/pipermail/python-dev/2017-Decill/151283 .html

तो आपके प्रश्न का उत्तर अब बन गया है: अजगर 3.6 में अपग्रेड करें! :)


1
यद्यपि मैं आपको दिए गए उदाहरण में वैसा ही व्यवहार देखता हूं, जैसे कि पायथन 3.6.4 के कार्यान्वयन में, मेरे लिए json.loads('{"2": 2, "1": 1}')बन जाता {'1': 1, '2': 2}है।
जुग

1
@fuglede यह क्रमबद्ध dict.__repr__कुंजियों की तरह दिखता है जबकि अंतर्निहित आदेश संरक्षित है। दूसरे शब्दों में, json.loads('{"2": 2, "1": 1}').items()है dict_items([('2', 2), ('1', 1)]), भले ही repr(json.loads('{"2": 2, "1": 1}'))है "{'1': 1, '2': 2}"
सिमोन चारेटे

@ शमोनच्रेते एचएम, हो सकता है; मैं वास्तव में conda के pkgs / main / win-64 :: python-3.6.4-h0c2934d_3 में अपने स्वयं के अवलोकन को पुन: उत्पन्न करने में असमर्थ हूं, इसलिए यह परीक्षण करना कठिन होगा।
फुगली

यह वास्तव में बहुत मदद नहीं करता है, क्योंकि "नाम" कुंजी अभी भी कुंजी के क्रम को बर्बाद कर देगा।
हब्रो

7

आप हमेशा हुकुम को डंप करने के अलावा चाबियों की सूची को लिख सकते हैं, और फिर OrderedDictसूची के माध्यम से पुनरावृत्ति करके पुनर्निर्माण कर सकते हैं ?


1
कम-तकनीकी समाधान के लिए +1। मैंने ऐसा तब किया है जब एक ही मुद्दे के साथ YAML के साथ काम कर रहा हूं, लेकिन डुप्लिकेट होने के लिए थोड़े लंगड़ा है, खासकर जब अंतर्निहित प्रारूप ऑर्डर को संरक्षित करता है। कुंजी-मूल्य वाले जोड़े को खोने से बचने के लिए भी समझदारी हो सकती है जो सभी स्पष्ट रूप से ऑर्डर किए गए आइटमों के बाद उन पर व्यवहार करते हुए, कुंजी की सूची से गायब हैं।
म्यू माइंड

2
निम्न तकनीकी समाधान भी संदर्भ को संरक्षित करता है जो अन्यथा आवश्यक रूप से निर्यातित प्रारूप में संरक्षित नहीं होता है (IOW; कोई व्यक्ति JSON देखता है और वहां स्पष्ट रूप से "इन कुंजियों को इस क्रम में रहना चाहिए" अगर वे इस पर हेरफेर करते हैं तो कुछ भी नहीं है)।
अम्बर

क्या निर्धारित करता है कि कुंजी "डंप" की सूची सही क्रम में हैं? नेस्टेड डाइचेस के बारे में क्या? ऐसा लगता है कि दोनों डंपिंग को संभालने की आवश्यकता होगी और पुनर्निर्माण को OrdereDictएस का उपयोग करके पुनरावृत्ति करने की आवश्यकता होगी ।
मार्टीन्यू

5

शब्दकोश के साथ-साथ कुंजी की क्रमबद्ध सूची को डंप करने के अलावा, एक और कम-तकनीकी समाधान, जिसमें स्पष्ट होने का लाभ है, कुंजी-मूल्य जोड़े की सूची (आदेशित) को डंप करना है ordered_dict.items(); लोडिंग एक सरल हैOrderedDict(<list of key-value pairs>) । यह इस तथ्य के बावजूद आदेश दिया गया शब्दकोश है कि JSON के पास यह अवधारणा नहीं है (JSON शब्दकोशों का कोई आदेश नहीं है)।

इस तथ्य का लाभ उठाना वास्तव में अच्छा है jsonजो ऑर्डरडीड को सही क्रम में डंप करता है। हालांकि, यह सामान्य रूप से भारी रूप से भारी है और जरूरी नहीं कि एक आदेश के रूप में सभी JSON शब्दकोशों को पढ़ने के लिए सार्थक हो (के माध्यम से)object_pairs_hook तर्क के ) के जाए, इसलिए केवल उन शब्दकोशों का एक स्पष्ट रूपांतरण जिसे ऑर्डर किया जाना चाहिए, समझ में भी आता है।


4

यदि आप object_pairs_hook पैरामीटर निर्दिष्ट करते हैं तो सामान्य रूप से उपयोग किया जाने वाला लोड कमांड काम करेगा :

import json
from  collections import OrderedDict
with open('foo.json', 'r') as fp:
    metrics_types = json.load(fp, object_pairs_hook=OrderedDict)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.