JSON से यूनिकोड के बजाय स्ट्रिंग ऑब्जेक्ट कैसे प्राप्त करें?


276

मैं ASCII से एन्कोडेड पाठ फ़ाइलों से JSON को पार्स करने के लिए पायथन 2 का उपयोग कर रहा हूं ।

जब jsonया तो या इन फ़ाइलों को लोड करने के साथ simplejson, मेरे सभी स्ट्रिंग मान स्ट्रिंग ऑब्जेक्ट्स के बजाय यूनिकोड ऑब्जेक्ट्स में डाले जाते हैं। समस्या यह है, मुझे कुछ पुस्तकालयों के साथ डेटा का उपयोग करना होगा जो केवल स्ट्रिंग ऑब्जेक्ट्स को स्वीकार करते हैं। मैं पुस्तकालयों को बदल नहीं सकता और न ही उन्हें अपडेट कर सकता हूं।

क्या यूनिकोड के बजाय स्ट्रिंग ऑब्जेक्ट प्राप्त करना संभव है?

उदाहरण

>>> import json
>>> original_list = ['a', 'b']
>>> json_list = json.dumps(original_list)
>>> json_list
'["a", "b"]'
>>> new_list = json.loads(json_list)
>>> new_list
[u'a', u'b']  # I want these to be of type `str`, not `unicode`

अपडेट करें

यह सवाल बहुत समय पहले पूछा गया था , जब मैं अजगर 2 के साथ फंस गया था । आज के लिए एक आसान और साफ समाधान पायथन के हाल के संस्करण का उपयोग करना है - अर्थात पायथन 3 और आगे।


1
Python3 के अंतर्गत कोई समस्या नहीं है, new_list में आइटम का प्रकार हैstr
GoingMyWay

1
पायथन 3k 'पायथन का हालिया संस्करण' नहीं है, यह सिर्फ एक वैकल्पिक शाखा है।
user2589273

11
दिसंबर 2017 में इस तरह की टिप्पणी को देखना अजीब है - पायथन 2 को हटा दिया गया है और 1 जनवरी 2020 के बाद कोई रखरखाव नहीं होगा, जो 2 साल से कम है: pythonclock.org
Zaar Hai

1
@ZARHai बहुत से लोग अपनी इच्छा के खिलाफ अजगर 2 में फंस गए हैं। कई एप्लिकेशन हैं जो स्वचालन और स्क्रिप्टिंग के लिए अपने स्वयं के पायथन संस्करण को एम्बेड करते हैं ताकि लोगों को इसका उपयोग तब तक करना होगा जब तक कि विक्रेता अपडेट न हो (मैं आपको माया, हौदिनी, Nuke ..) देख रहा हूं
Geordie

1
@Geordie मैं निश्चित रूप से जानता और समझता हूं। मेरी टिप्पणी शब्दावली के बारे में थी - पायथन एक "वैकल्पिक शाखा" नहीं है, बल्कि उन लोगों के लिए वैकल्पिक (दंडनीय इरादा) की दुर्भाग्यपूर्ण कमी है जो इसके साथ फंस गए हैं।
ज़ार है

जवाबों:


101

के साथ एक समाधान object_hook

import json

def json_load_byteified(file_handle):
    return _byteify(
        json.load(file_handle, object_hook=_byteify),
        ignore_dicts=True
    )

def json_loads_byteified(json_text):
    return _byteify(
        json.loads(json_text, object_hook=_byteify),
        ignore_dicts=True
    )

def _byteify(data, ignore_dicts = False):
    # if this is a unicode string, return its string representation
    if isinstance(data, unicode):
        return data.encode('utf-8')
    # if this is a list of values, return list of byteified values
    if isinstance(data, list):
        return [ _byteify(item, ignore_dicts=True) for item in data ]
    # if this is a dictionary, return dictionary of byteified keys and values
    # but only if we haven't already byteified it
    if isinstance(data, dict) and not ignore_dicts:
        return {
            _byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True)
            for key, value in data.iteritems()
        }
    # if it's anything else, return it in its original form
    return data

उदाहरण का उपयोग:

>>> json_loads_byteified('{"Hello": "World"}')
{'Hello': 'World'}
>>> json_loads_byteified('"I am a top-level string"')
'I am a top-level string'
>>> json_loads_byteified('7')
7
>>> json_loads_byteified('["I am inside a list"]')
['I am inside a list']
>>> json_loads_byteified('[[[[[[[["I am inside a big nest of lists"]]]]]]]]')
[[[[[[[['I am inside a big nest of lists']]]]]]]]
>>> json_loads_byteified('{"foo": "bar", "things": [7, {"qux": "baz", "moo": {"cow": ["milk"]}}]}')
{'things': [7, {'qux': 'baz', 'moo': {'cow': ['milk']}}], 'foo': 'bar'}
>>> json_load_byteified(open('somefile.json'))
{'more json': 'from a file'}

यह कैसे काम करता है और मैं इसका उपयोग क्यों करूंगा?

मार्क अमेरी का कार्य इन लोगों की तुलना में छोटा और स्पष्ट है, तो उनका क्या मतलब है? आप उनका उपयोग क्यों करना चाहेंगे?

विशुद्ध रूप से प्रदर्शन के लिए । मार्क का उत्तर JSON टेक्स्ट को पूरी तरह से यूनिकोड स्ट्रिंग्स के साथ पूरी तरह से पहले डिकोड करता है, फिर सभी स्ट्रिंग्स को बाइट स्ट्रिंग्स में बदलने के लिए पूरे डिकोड किए गए मान के माध्यम से पुन: बनाता है। इसके कुछ अवांछनीय प्रभाव हैं:

  • पूरे डिकोड किए गए ढांचे की एक प्रति स्मृति में बन जाती है
  • यदि आपकी JSON ऑब्जेक्ट वास्तव में गहरी नेस्टेड है (500 के स्तर या अधिक) तो आप पायथन की अधिकतम पुनरावृत्ति की गहराई से टकराएंगे

इस उत्तर उन प्रदर्शन के मुद्दों के दोनों का उपयोग करके कम कर object_hookके पैरामीटर json.loadऔर json.loads। से डॉक्स :

object_hookएक वैकल्पिक फ़ंक्शन है जिसे किसी भी वस्तु के शाब्दिक डिकोड (a dict) के परिणाम के साथ कहा जाएगा । इसके बदले object_hook के रिटर्न मान का उपयोग किया जाएगा dict। इस सुविधा का उपयोग कस्टम डिकोडर्स को लागू करने के लिए किया जा सकता है

चूंकि डिक्शनरी ने कई स्तरों पर दूसरे डिक्शनरों में गहरे घोंसले बना लिए हैं, object_hook जैसे कि वे डीकोड हो गए हैं , हम उस बिंदु पर उनके अंदर मौजूद किसी भी तार या सूची को बाइट कर सकते हैं और बाद में डीप रिकर्स की आवश्यकता से बच सकते हैं।

मार्क का उत्तर उपयोग करने के लिए उपयुक्त नहीं है object_hookक्योंकि यह खड़ा है, क्योंकि यह नेस्टेड शब्दकोशों में पुनरावृत्ति करता है। हम उस उत्तर में ignore_dictsपैरामीटर के साथ उस पुनरावृत्ति को रोकते हैं _byteify, जो इसे हर समय पास करता है, सिवाय इसके कि जब object_hookइसे नया dictकरने के लिए पास किया जाए। ignore_dictsध्वज बताता है _byteifyकी अनदेखी करने dictके बाद से वे पहले से ही byteified किया गया है।

अंत में, परिणाम पर हमारी कॉल json_load_byteifiedऔर json_loads_byteifiedकॉल _byteify(के साथ ignore_dicts=True) वापस आ गई json.loadया json.loadsउस मामले को संभालने के लिए जहां JSON पाठ को डिकोड किया जा रहा है dict, शीर्ष स्तर पर नहीं है ।


1
यहाँ दृष्टिकोण के लिए +1; जब मैंने पहली बार इसे पढ़ा था, तो मैं वास्तव में इसे समझ नहीं पाया था, लेकिन आखिरकार ट्रैविस जेन्सेन के उत्तर के प्रकाश में इसे फिर से पढ़ना कब समझा। मैंने यह स्पष्ट करने की उम्मीद में एक बहुत ही आक्रामक संपादन किया है कि यह कैसे काम करता है और मेरे उत्तर पर इसके फायदे क्या हैं। कोड का मुख्य विचार अछूता रहता है, लेकिन मैंने बाकी सभी चीजों को बहुत संशोधित किया है। यदि आप इस पर आपत्ति करते हैं, तो मेरा संपादन वापस लेने के लिए स्वतंत्र महसूस करें - यह आपका उत्तर है!
मार्क अमेरी

कोई समस्या नहीं मार्क, बहुत धन्यवाद। मुझे आपका संपादन पसंद है, यह मेरे मूल से बहुत अधिक व्याख्यात्मक है। हो सकता है, एक दिन, मैं और अधिक संक्षिप्त जवाब देना सीखूंगा।
मिरिक मिस्कुफ

2
यह महान समाधान है; कुशल और सुरुचिपूर्ण। हालांकि, यदि आप पायथन <2.7 के दायरे में फंस गए हैं, तो जैसा कि मैं हूं, आपको लाइन को बदलने की आवश्यकता होगी: इसके return { byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True) for key, value in data.iteritems() }साथ return dict((_byteify(key, ignore_dicts=True), _byteify(value, ignore_dicts=True)) for key, value in data.iteritems())काम करने के लिए।
रिचर्ड डन

मुझे लगता है कि आप पुनरावृत्ति गहराई के मुद्दे के बारे में गलत हैं। तुम्हारे साथ, मैं 990 तक जा सकता हूं json_loads_byteified('[' * 990 + ']' * 990):। 991 के साथ यह दुर्घटनाग्रस्त हो जाता है। मार्क अभी भी 991 के साथ काम करता है byteify(json.loads('[' * 991 + ']' * 991)):। यह 992 पर दुर्घटनाग्रस्त हो जाता है। इसलिए कम से कम इस परीक्षण में, मार्क ने जो कहा, उसके विपरीत गहराई तक जा सकते हैं।
स्टीफन पोचमैन 21

@MarkAmery मेरी उपरोक्त टिप्पणी के बारे में आप क्या सोचते हैं? (मैंने अभी-अभी संपादित इतिहास में देखा कि यह वास्तव में आप ही थे जिन्होंने उस दावे को जोड़ा)।
स्टीफन पोचमैन

180

हालांकि यहाँ कुछ अच्छे उत्तर हैं, मैंने अपनी JSON फ़ाइलों को पार्स करने के लिए PyYAML का उपयोग किया , क्योंकि यह कुंजी और मानों को strटाइप के बजाय स्ट्रिंग्स के रूप में देता है unicode। क्योंकि JSON YAML का एक सबसेट है जो यह अच्छी तरह से काम करता है:

>>> import json
>>> import yaml
>>> list_org = ['a', 'b']
>>> list_dump = json.dumps(list_org)
>>> list_dump
'["a", "b"]'
>>> json.loads(list_dump)
[u'a', u'b']
>>> yaml.safe_load(list_dump)
['a', 'b']

टिप्पणियाँ

हालांकि ध्यान देने योग्य कुछ बातें:

  • मुझे स्ट्रिंग ऑब्जेक्ट मिलते हैं क्योंकि मेरी सभी प्रविष्टियाँ ASCII एनकोडेड हैं । अगर मैं यूनिकोड एनकोडेड प्रविष्टियों का उपयोग करता हूं, तो मैं उन्हें यूनिकोड ऑब्जेक्ट के रूप में वापस प्राप्त करूंगा - कोई रूपांतरण नहीं है!

  • आपको (शायद हमेशा) PyYAML के safe_loadफ़ंक्शन का उपयोग करना चाहिए ; यदि आप JSON फ़ाइलों को लोड करने के लिए इसका उपयोग करते हैं, तो आपको loadवैसे भी फ़ंक्शन की "अतिरिक्त शक्ति" की आवश्यकता नहीं है।

  • यदि आप एक YAML पार्सर चाहते हैं जिसमें कल्पना के 1.2 संस्करण के लिए और अधिक समर्थन है (और सही ढंग से बहुत कम संख्या में पार्स ) रुआमल यमल का प्रयास करें : pip install ruamel.yamlऔर import ruamel.yaml as yamlमुझे अपने परीक्षणों में सभी की आवश्यकता थी।

रूपांतरण

जैसा कि कहा गया है, कोई रूपांतरण नहीं है! यदि आप केवल ASCII मूल्यों के साथ सौदा करना सुनिश्चित नहीं कर सकते हैं (और आप ज्यादातर समय सुनिश्चित नहीं हो सकते हैं), तो रूपांतरण फ़ंक्शन का बेहतर उपयोग करें :

मैंने मार्क अमेरी से एक दो बार इस्तेमाल किया , यह बहुत अच्छा काम करता है और इसका उपयोग करना बहुत आसान है। आप object_hookइसके बजाय एक समान फ़ंक्शन का उपयोग कर सकते हैं , क्योंकि इससे आपको बड़ी फ़ाइलों पर प्रदर्शन को बढ़ावा मिल सकता है। उस के लिए मिरस्क मिस्कुफ से थोड़ा अधिक शामिल जवाब देखें ।


8
यदि आप इस उत्तर का उपयोग करने का निर्णय लेते हैं तो थोड़ा ध्यान रखें। यह ब्रूटस के मामले के लिए पूरी तरह से काम करता है, लेकिन केवल इसलिए कि वह जानता है कि उसके डेटा में केवल ASCII-एनकोडेबल वर्ण हैं। यदि आपके पास वह गारंटी नहीं है, तो यह उत्तर काम नहीं करेगा। उदाहरण के लिए, yaml.load(json.dumps([u'a', u'£', u'É']))पायथन शेल पर अमल करने की कोशिश करें और निरीक्षण करें कि आप वापस आ गए हैं ['a', u'\xa3', u'\xc9'](जिसमें unicodeतार शामिल हैं)। यदि आप यह सुनिश्चित नहीं कर सकते हैं कि आपके डेटा में केवल ASCII वर्ण सेट से वर्ण हैं, तो आपको इसके बजाय एक अलग दृष्टिकोण का उपयोग करना चाहिए (मैं अपने उत्तर की अनुशंसा करता हूं)।
मार्क अमेरी

1
YAML भी [u'a', u'b']सावधान का उपयोग करता है ।
कार्लोस कैला

1
यह अच्छा है, लेकिन यह कम संख्या के साथ काम नहीं करता है .. यहां देखें: stackoverflow.com/questions/30458977/…
Oren

@Oren: यह YAML कल्पना में लेकिन PyYAML पार्सर में कोई त्रुटि नहीं है । Ruamel से YAML पार्सर काम करता है।
ब्रूटस

मैं चाहता हूँ कि ["a", "b"] जैसे ['a', 'b'] @Brutus
user60679

141

JSON मॉड्यूल फ़ंक्शंस बाइट स्ट्रिंग्स को यूनिकोड स्ट्रिंग्स के बजाय बनाने के लिए कोई अंतर्निहित विकल्प नहीं है। हालाँकि, यह छोटा और सरल पुनरावर्ती कार्य किसी भी डिकोड किए गए JSON ऑब्जेक्ट को यूनिकोड स्ट्रिंग्स का उपयोग करके UTF-8-एन्कोडेड बाइट स्ट्रिंग्स में बदल देगा:

def byteify(input):
    if isinstance(input, dict):
        return {byteify(key): byteify(value)
                for key, value in input.iteritems()}
    elif isinstance(input, list):
        return [byteify(element) for element in input]
    elif isinstance(input, unicode):
        return input.encode('utf-8')
    else:
        return input

इसे केवल उस आउटपुट पर कॉल करें जिसे आप कॉल json.loadया json.loadsकॉल से प्राप्त करते हैं।

नोटों की एक जोड़ी:

  • अजगर 2.6 का समर्थन करने के या इससे पहले, की जगह return {byteify(key): byteify(value) for key, value in input.iteritems()}के साथ return dict([(byteify(key), byteify(value)) for key, value in input.iteritems()]), के बाद से शब्दकोश comprehensions अजगर 2.7 जब तक समर्थित नहीं कर रहे थे।
  • चूंकि यह उत्तर पूरे डिकोड किए गए ऑब्जेक्ट के माध्यम से पुनरावृत्ति करता है, इसमें अवांछनीय प्रदर्शन विशेषताओं की एक जोड़ी होती है जिसे बहुत सावधानी से object_hookया object_pairs_hookमापदंडों के उपयोग से बचा जा सकता है । Mirec Miskuf का उत्तर अभी तक केवल एक ही है जो इसे सही तरीके से खींचने का प्रबंधन करता है, हालांकि एक परिणाम के रूप में, यह मेरे दृष्टिकोण से काफी अधिक जटिल है।

1
मुझे यह पसंद है - यह कोई अनदेखी नहीं है - यह पहचान रहा है कि जब लोग "तार" और "अस्की" कहते हैं, तो वे ज्यादातर भोलेपन से मतलब करते थे कि वे सैद्धांतिक बाइट चाहते थे। (और नहीं ascii के रूप में वे अभी भी दूसरे छोर पर पाउंड संकेत चाहते हैं)
डैनी स्टेपल

मुझे यह पसंद है, यह लगभग उसी तरह काम करता है जैसे मेरा सुंदर प्रिंटर काम करता है, क्योंकि मुझे पता है कि जसन टपल नहीं बनाते हैं, आपको टपल के लिए भी अपवाद जोड़ना चाहिए।
y.petremann

यह बहुत ही अयोग्य है, जिसके लिए आपको पुनरावृत्ति करने वाले नोड्स की आवश्यकता होती है, जिनकी आपको आवश्यकता नहीं हो सकती है। Json मॉड्यूल आपको अधिक कुशलतापूर्वक ऐसा करने के लिए हुक देता है। नीचे दिए गए उत्तर का उपयोग object_hookवास्तव में इस एक की तुलना में बहुत बुरा है, हालांकि, लेकिन, का उपयोग करते हुए object_pairs_hook, आप एक उचित कुशल विधि के साथ आ सकते हैं जिसमें नोड्स की पुनरावृत्ति या पुनरावृत्ति की आवश्यकता नहीं होती है जिसमें तार नहीं होते हैं।
ट्रैविस जेन्सेन

1
@TravisJensen दिलचस्प। इस object_pairs_hookविधि को समझने के लिए विधि शायद बहुत थोड़ी कठिन है (आपको यह समझने की ज़रूरत है कि पैरामीटर कैसे काम करता है और सूचियों और डीकट्स को अलग-अलग हैंडलिंग की आवश्यकता क्यों है), और प्रदर्शन का लाभ अधिकांश लोगों के लिए मायने नहीं रखेगा ... लेकिन मुझे उम्मीद है यह अस्तित्व में है, विशेष रूप से किसी भी असामान्य रूप से गहरी नेस्टेड JSON ऑब्जेक्ट के साथ काम करने के लिए।
मार्क अमेरी

प्लस 1 यह सबसे संक्षिप्त जवाब है; इसके अलावा PyYAML स्थापित करने के लिए एक दर्द है। केवल बेहतर चीज किसी भी तरह से रूपांतरण को माइक्रो-स्ट्रीम करेगी ताकि यह 4X मेमोरी का उपयोग न करे।
personal_cloud

74

आप किसी कनवर्टर में पास होने के object_hookलिए पैरामीटर का उपयोग कर सकते हैं json.loads। आपको इस तथ्य के बाद रूपांतरण करने की आवश्यकता नहीं है। jsonमॉड्यूल हमेशा पारित करेंगे object_hookdicts केवल, और यह रिकर्सिवली नेस्टेड dicts में पारित होगा, ताकि आप नेस्टेड dicts में अपने आप को recurse करने की जरूरत नहीं है। मुझे नहीं लगता कि मैं यूनिकोड स्ट्रिंग्स को वेल्स शो जैसी संख्याओं में परिवर्तित करूंगा। यदि यह एक यूनिकोड स्ट्रिंग है, तो इसे JSON फ़ाइल में स्ट्रिंग के रूप में उद्धृत किया गया था, इसलिए इसे स्ट्रिंग माना जाता है (या फ़ाइल खराब है)।

इसके अलावा, मैं str(val)एक unicodeवस्तु पर कुछ करने से बचने की कोशिश करूँगा । आपको value.encode(encoding)एक मान्य एन्कोडिंग के साथ उपयोग करना चाहिए , जो आपके बाहरी देयता की अपेक्षा करता है।

इसलिए, उदाहरण के लिए:

def _decode_list(data):
    rv = []
    for item in data:
        if isinstance(item, unicode):
            item = item.encode('utf-8')
        elif isinstance(item, list):
            item = _decode_list(item)
        elif isinstance(item, dict):
            item = _decode_dict(item)
        rv.append(item)
    return rv

def _decode_dict(data):
    rv = {}
    for key, value in data.iteritems():
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        elif isinstance(value, list):
            value = _decode_list(value)
        elif isinstance(value, dict):
            value = _decode_dict(value)
        rv[key] = value
    return rv

obj = json.loads(s, object_hook=_decode_dict)

3
यदि ऑब्जेक्ट sJSON Object(कुंजी का एक अनियोजित संग्रह है: ':' चरित्र के साथ कुंजी और मान को अलग करता है, तो अल्पविराम से अलग किया गया है और घुंघराले ब्रेसिज़ में संलग्न है) ठीक है, लेकिन ऐसा नहीं है, कहते हैं, JSON Array। इसलिए यदि JSON Arrayजैसा दिया जाता है ["a", "b"], तो परिणाम अभी भी होगा [u'a', u'b']। वर्तमान में उपलब्ध कोई भी अन्य कस्टमाइज़िंग हुक-प्रकार के पैरामीटर json.loads()काम नहीं कर सकता है।
मार्टीन्यू

2
चूंकि, जैसा कि आपने उल्लेख किया है, jsonमॉड्यूल पुनरावर्ती रूप से नेस्टेड dictएस में पारित होगा , दो कार्यों में उनके लिए जांच करना अनावश्यक है - इसलिए दो elifक्लॉज जो उनके लिए जांच करते हैं उन्हें हटा दिया जाना चाहिए।
मार्टीन्यू

1
ध्यान दें कि एक अंडरस्कोर के साथ फ़ंक्शन नाम शुरू करना आयात बयानों के लिए एक विशेष अर्थ है। यदि आप इन कार्यों को यूटिलिटीहोम नामक एक फ़ाइल में रखते हैं और किसी अन्य फ़ाइल में करते हैं from Utility import *, तो उस अंडरस्कोर के कारण फ़ंक्शन दिखाई नहीं देंगे ।
एम काटज़

1
यह वास्तव में बुरा विचार है। object_hookप्रत्येक जन्स ऑब्जेक्ट के लिए कॉल किया जाता है, इसलिए यदि आप जो दिया जाता है, उसमें पुनरावृत्ति करते हैं, तो आप उन चीजों को फिर से "बाइटीफाइंग" करते हैं जिन्हें आपने पहले ही "बाइटीफाइड" कर दिया है। ऑब्जेक्ट के आकार के साथ प्रदर्शन ज्यामितीय रूप से बढ़ने वाला है। मैंने यहां एक उत्तर शामिल किया है जो उपयोग करता है object_pairs_hookऔर उस समस्या से ग्रस्त नहीं है।
ट्रैविस जेन्सेन

38

ऐसा इसलिए है क्योंकि स्ट्रिंग ऑब्जेक्ट्स और यूनिकोड ऑब्जेक्ट्स के बीच json का कोई अंतर नहीं है। वे सभी जावास्क्रिप्ट में तार हैं।

मुझे लगता है कि JSON यूनिकोड ऑब्जेक्ट को वापस करने के लिए सही है । वास्तव में, मैं कुछ भी कम स्वीकार नहीं करूँगा, क्योंकि जावास्क्रिप्ट स्ट्रिंग्स वास्तव में unicodeऑब्जेक्ट्स (यानी JSON (जावास्क्रिप्ट) स्ट्रिंग्स किसी भी प्रकार के यूनिकोड वर्ण को संग्रहीत कर सकते हैं ) इसलिए यह unicodeJSON से स्ट्रिंग्स का अनुवाद करते समय ऑब्जेक्ट बनाने के लिए समझ में आता है । सादा तार बस फिट नहीं होगा क्योंकि लाइब्रेरी को आपके इच्छित एन्कोडिंग का अनुमान लगाना होगा।

unicodeहर जगह स्ट्रिंग ऑब्जेक्ट्स का उपयोग करना बेहतर है। तो आपका सबसे अच्छा विकल्प अपने पुस्तकालयों को अपडेट करना है ताकि वे यूनिकोड ऑब्जेक्ट से निपट सकें।

लेकिन अगर आप वास्तव में बाइटस्ट्रेस चाहते हैं, तो परिणामों को अपनी पसंद के एन्कोडिंग में एनकोड करें:

>>> nl = json.loads(js)
>>> nl
[u'a', u'b']
>>> nl = [s.encode('utf-8') for s in nl]
>>> nl
['a', 'b']

धन्यवाद nosklo, यही मैंने पहले किया है। लेकिन जैसा कि मैंने कहा, मेरे द्वारा उपयोग किया जाने वाला वास्तविक डेटा बहुत अच्छा है और सभी, इसलिए इसने कुछ ओवरहेड क्विट की शुरुआत की। मैं अभी भी एक स्वचालित समाधान की तलाश कर रहा हूं ... वहां कम से कम एक बग रिपोर्ट है जहां लोग सिंपलसन के बारे में यूनिकोड के बजाय स्ट्रिंग वस्तुओं को वापस करने की शिकायत करते हैं।
ब्रूटस

1
@ ब्रुटस: मुझे लगता है कि यूनिकोड ऑब्जेक्ट को वापस करने के लिए json सही है। वास्तव में, मैं कुछ भी कम स्वीकार नहीं करता, क्योंकि जावास्क्रिप्ट स्ट्रिंग्स वास्तव में यूनिकोड ऑब्जेक्ट हैं। मेरा मतलब है कि json (जावास्क्रिप्ट) तार किसी भी प्रकार के यूनिकोड वर्ण को संग्रहीत कर सकते हैं, इसलिए यह json से अनुवाद करते समय यूनिकोड ऑब्जेक्ट बनाने के लिए समझ में आता है। आपको वास्तव में इसके बजाय अपने पुस्तकालयों को ठीक करना चाहिए।
nosklo

16

एक आसान काम मौजूद है।

टीएल; डीआर - के ast.literal_eval()बजाय का उपयोग करें json.loads()। दोनों astऔर jsonमानक पुस्तकालय में हैं।

हालांकि एक 'सही' जवाब नहीं है, यह एक बहुत दूर हो जाता है अगर आपकी योजना यूनिकोड को पूरी तरह से अनदेखा करना है। पायथन 2.7 में

import json, ast
d = { 'field' : 'value' }
print "JSON Fail: ", json.loads(json.dumps(d))
print "AST Win:", ast.literal_eval(json.dumps(d))

देता है:

JSON Fail:  {u'field': u'value'}
AST Win: {'field': 'value'}

यह अधिक बालों वाला हो जाता है जब कुछ ऑब्जेक्ट वास्तव में यूनिकोड के तार होते हैं। पूरा जवाब बालों को जल्दी मिलता है।


11
बेहतर होगा कि आपके json में कोई भी null, trueया falseमान शामिल नहीं हैं , क्योंकि वे अजगर में मान्य नहीं हैं और literal_eval()विफल होने का कारण बनेंगे।
8:s34oɈ

3
@ SONs ​​doesn'toɈ इससे भी बेहतर उम्मीद है कि आपके JSON में \/स्ट्रिंग के अंदर एक बचा हुआ सॉलिडस ( ) नहीं है, या एक यूनिकोड एस्केप सीक्वेंस (जैसे "\u0061", जो लिखने का दूसरा तरीका है "a")। पायथन का शाब्दिक वाक्य-विन्यास कई तरह से JSON के साथ असंगत है, और मैं किसी भी स्क्रिप्ट के लिए इस उत्तर पर भरोसा नहीं करूंगा जिसे मैं फेंकने वाला नहीं था।
मार्क अमेरी

लोग सही कह रहे हैं कि यदि स्ट्रिंग वास्तव में यूनिकोड है तो यह उत्तर विफल हो जाता है, लेकिन यदि ऐसा होता तो हम स्ट्रिंग स्ट्रिंग में नहीं जा पाएंगे। एक जवाब के लिए +1 जो केवल तभी काम करता है जब वह काम करता है और अन्यथा अपवाद फेंकता है
स्टीफन सुलिवन

यदि संभव हो तो jsonडेटा को डंप करने के लिए उपयोग न करें , बस printअगर अजगर चल रहा है तो उपयोग करें । तब ast.literal_evalकाम करता है
जीन फ़्राँस्वा Fabre

11

माइक ब्रेनन का जवाब करीब है, लेकिन पूरे ढांचे को फिर से आगे बढ़ाने का कोई कारण नहीं है। यदि आप object_hook_pairs(पायथन 2.7+) पैरामीटर का उपयोग करते हैं :

object_pairs_hookएक वैकल्पिक कार्य है जिसे किसी भी वस्तु के शाब्दिक परिणाम के साथ कहा जाएगा जिसे जोड़ियों की क्रमबद्ध सूची के साथ डिकोड किया गया है। के बदले मूल्य का object_pairs_hookउपयोग किया जाएगा dict। इस सुविधा का उपयोग कस्टम डिकोडर्स को लागू करने के लिए किया जा सकता है जो इस आदेश पर भरोसा करते हैं कि कुंजी और मूल्य जोड़े डिकोड किए गए हैं (उदाहरण के लिए, collections.OrderedDictसम्मिलन के आदेश को याद करेंगे)। यदि object_hookयह भी परिभाषित किया गया है, object_pairs_hookप्राथमिकता लेता है।

इसके साथ, आप प्रत्येक JSON ऑब्जेक्ट को आपके हवाले कर देते हैं, ताकि आप पुनरावर्तन की आवश्यकता के साथ डिकोडिंग कर सकें:

def deunicodify_hook(pairs):
    new_pairs = []
    for key, value in pairs:
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        new_pairs.append((key, value))
    return dict(new_pairs)

In [52]: open('test.json').read()
Out[52]: '{"1": "hello", "abc": [1, 2, 3], "def": {"hi": "mom"}, "boo": [1, "hi", "moo", {"5": "some"}]}'                                        

In [53]: json.load(open('test.json'))
Out[53]: 
{u'1': u'hello',
 u'abc': [1, 2, 3],
 u'boo': [1, u'hi', u'moo', {u'5': u'some'}],
 u'def': {u'hi': u'mom'}}

In [54]: json.load(open('test.json'), object_pairs_hook=deunicodify_hook)
Out[54]: 
{'1': 'hello',
 'abc': [1, 2, 3],
 'boo': [1, 'hi', 'moo', {'5': 'some'}],
 'def': {'hi': 'mom'}}

ध्यान दें कि मुझे कभी भी हुक को पुन: कॉल करने की आवश्यकता नहीं है क्योंकि प्रत्येक वस्तु हुक को सौंप दी जाएगी जब आप उपयोग करेंगे object_pairs_hook। आपको सूचियों के बारे में ध्यान रखने की ज़रूरत है, लेकिन जैसा कि आप देख सकते हैं, सूची के भीतर एक वस्तु को ठीक से परिवर्तित किया जाएगा, और आपको ऐसा करने के लिए पुनरावृत्ति करने की आवश्यकता नहीं है।

संपादित करें: एक सहकर्मी ने बताया कि पायथन 2.6 में नहीं है object_hook_pairs। आप अभी भी Python2.6 का उपयोग बहुत कम परिवर्तन करके कर सकते हैं। ऊपर हुक में, बदलें:

for key, value in pairs:

सेवा

for key, value in pairs.iteritems():

इसके object_hookबजाय का उपयोग करें object_pairs_hook:

In [66]: json.load(open('test.json'), object_hook=deunicodify_hook)
Out[66]: 
{'1': 'hello',
 'abc': [1, 2, 3],
 'boo': [1, 'hi', 'moo', {'5': 'some'}],
 'def': {'hi': 'mom'}}

object_pairs_hookJSON ऑब्जेक्ट में प्रत्येक ऑब्जेक्ट के लिए एक कम शब्दकोश में परिणाम का उपयोग करना , जो, यदि आप एक विशाल दस्तावेज़ पार्स कर रहे थे, तो हो सकता है।


1
यह साफ-सुथरा है और हरे रंग के चेकमार्क के योग्य है (जो ब्रूटस के पास है, अदभुत, पहले से ही उदारतापूर्वक पारित किया गया है क्योंकि बेहतर उत्तर आए हैं)। लेकिन ... आप वास्तव में इस सूची को ठीक से क्यों नहीं संभालते हैं deunicodify_hookजो आप इस उत्तर में प्रदर्शित करते हैं? फिलहाल, आपके पास कार्यान्वयन है deunicodify_hookजो सूचियों पर पुनरावृति नहीं करता है और उनके भीतर तार और सूचियों को संपीड़ित करता है, और इस प्रकार आप जो आउटपुट प्रदर्शित कर रहे हैं वह उस आउटपुट से मेल नहीं खाता है जो वास्तव में आपके हुक का उत्पादन करेगा। इसे ठीक करें, और यह उत्तर मेरे लिए बेहतर होगा।
मार्क अमेरी

नगण्य: मैं यह भी सुझाव दूंगा कि आप जो यहां उपयोग कर रहे हैं (जो मुझे लगता है कि आयरनपायथॉन है) के बजाय साधारण CPython दुभाषिया के साथ फ़ंक्शन का प्रदर्शन करना चाहिए? सीपीथॉन दुभाषिया अधिकांश पायथन उपयोगकर्ताओं के लिए अधिक परिचित है और मेरी राय में, प्रेटियर है।
मार्क अमेरी

यह मेरे लिए काम नहीं करता है, लेकिन मुझे यकीन है कि यह कुछ क्विक है कि मैं क्या कर रहा हूं ... मैं एक सूची को एक बड़े जसन डॉक से एक फाइल में स्टोर कर रहा हूं। चाहे मैं इस ऑब्जेक्ट के साथ या इसके बिना लोड करता हूं_ जोड़े, हर आइटम यूनिकोड पर आता है। अरे।
rsaw

1
@rsaw अच्छा बिंदु! चूंकि object_pairs_hookकेवल ऑब्जेक्ट्स के लिए कॉल किया जाता है , यदि आपके JSON टेक्स्ट में शीर्ष स्तर पर स्ट्रिंग्स की सूची है, तो यह समाधान विफल हो जाएगा। वहाँ से इसे वापस करने का कोई तरीका नहीं है बिना किसी फ़ंक्शन को कॉल किए गए चीज़ से json.load; कोई भी json.loadहुक गारंटी नहीं दे सकता है कि आप हर स्ट्रिंग से निपटने में सक्षम होंगे। मुझे लगता है कि हुक का उपयोग करने के लिए मेरे समाधान की सिफारिश करते रहना मेरे लिए एक बड़ा पर्याप्त दोष है।
मार्क अमेरी

-1 क्योंकि मुझे सिर्फ एहसास हुआ कि मिरेक मिस्कुफ़ ने पहले ही एक ऑब्जेक्ट-हुक उत्तर पोस्ट किया है , जिसमें न तो माइक ब्रेनन के दृष्टिकोण के नुकसान हैं (कई बार एक ही शब्दकोशों को फिर से बाइट करता है) और न ही इस में से एक (नॉट लिस्ट या टॉप-लेवल लिस्ट को बाइट करने में विफल रहता है) या तार)। मुझे यकीन नहीं है कि उसका जवाब लगभग किसी भी ध्यान से कम नहीं हुआ है जबकि यह एक - जो हीन है - ने तेजी से वोट हासिल किए हैं।
मार्क अमेरी

9

मुझे डर है कि सिंपलसन लाइब्रेरी के भीतर इसे स्वचालित रूप से प्राप्त करने का कोई तरीका नहीं है।

सिंपलसन में स्कैनर और डिकोडर को यूनिकोड टेक्स्ट का निर्माण करने के लिए डिज़ाइन किया गया है। ऐसा करने के लिए, पुस्तकालय एक फ़ंक्शन का उपयोग करता है c_scanstring(यदि यह उपलब्ध है, गति के लिए), या py_scanstringयदि सी संस्करण उपलब्ध नहीं है। scanstringसमारोह लगभग हर दिनचर्या simplejson एक संरचना है कि पाठ शामिल हो सकता है डीकोड करने के लिए है कि ने कई बार कहा जाता है। आपको या तो simplejson.decoder में scanstringमूल्य का बंदरबांट करना होगा, या सबक्लास करना होगा और किसी भी चीज़ के JSONDecoderअपने संपूर्ण कार्यान्वयन को प्रदान करना होगा जिसमें पाठ शामिल हो सकता है।

कारण यह है कि साधारणजन यूनिकोड का उत्पादन करता है, हालांकि, यह है कि जोंस कल्पना विशेष रूप से उल्लेख करती है कि "एक स्ट्रिंग शून्य या अधिक यूनिकोड वर्णों का एक संग्रह है" ... यूनिकोड के लिए समर्थन को प्रारूप के भाग के रूप में ही ग्रहण किया जाता है। सिंपलजसन का scanstringकार्यान्वयन यूनिकोड से बचने (यहां तक ​​कि विकृत बहु-बाइट चारसेट अभ्यावेदन के लिए त्रुटि-जांच) को स्कैन करने और व्याख्या करने के लिए अब तक चला जाता है, इसलिए यह एकमात्र तरीका है जो आपको मज़बूती से आपके लिए मूल्य वापस कर सकता है जैसा कि यूनिकोड है।

यदि आपके पास एक वृद्ध पुस्तकालय है, जिसकी आवश्यकता है str, तो मैं आपको सलाह देता हूं कि पार्सिंग के बाद नेस्टेड डेटा संरचना की खोज करें (जो मैं स्वीकार करता हूं कि आपने स्पष्ट रूप से कहा था कि आप बचना चाहते थे ... क्षमा करें), या शायद अपने पुस्तकालयों को किसी प्रकार से लपेटें। मुखौटा जहां आप अधिक ग्रेन्युलर स्तर पर इनपुट मापदंडों की मालिश कर सकते हैं। दूसरा दृष्टिकोण पहले की तुलना में अधिक प्रबंधनीय हो सकता है यदि आपकी डेटा संरचना वास्तव में गहराई से नेस्टेड हैं।


4

जैसा कि मार्क (एमी) ​​सही ढंग से नोट करता है: एक डंप डंप पर Pyamaml के डिसेरिएलाइज़र का उपयोग करना केवल अगर आपके पास ASCII है तो ही काम करता है। कम से कम बॉक्स से बाहर।

PyYaml दृष्टिकोण पर दो त्वरित टिप्पणियां:

  1. कभी भी फ़ील्ड से डेटा पर yaml.load का उपयोग करें। इसकी एक विशेषता (!) संरचना के भीतर छिपे हुए मनमाने कोड को निष्पादित करने के लिए यमल की है।

  2. आप इसके माध्यम से गैर ASCII के लिए भी काम कर सकते हैं:

    def to_utf8(loader, node):
        return loader.construct_scalar(node).encode('utf-8')
    yaml.add_constructor(u'tag:yaml.org,2002:str', to_utf8)

लेकिन मार्क अमेरी के जवाब की तुलना में प्रदर्शन बुद्धिमान है:

दो तरीकों पर कुछ गहरी नेस्टेड सैंपल डाइक को फेंकते हुए, मुझे यह मिल जाता है (dt [j] = json.loads के टाइम डेल्टा के साथ) (json.dumps (m))):

     dt[yaml.safe_load(json.dumps(m))] =~ 100 * dt[j]
     dt[byteify recursion(Mark Amery)] =~   5 * dt[j]

तो deserialization सहित पूरी तरह से पेड़ चलना और एन्कोडिंग, जोसन के सी आधारित कार्यान्वयन के परिमाण के क्रम के भीतर। मुझे यह उल्लेखनीय रूप से तेज लगता है और इसकी गहराई से नेस्टेड संरचनाओं पर यमल लोड की तुलना में अधिक मजबूत है। और yaml.load को देखते हुए कम सुरक्षा त्रुटि होती है।

=> हालांकि मैं एक पॉइंटर की सराहना करूंगा C केवल आधारित कनवर्टर को बाइटीफ फ़ंक्शन को डिफ़ॉल्ट उत्तर होना चाहिए।

यह विशेष रूप से सच है अगर आपका json संरचना उपयोगकर्ता इनपुट वाले क्षेत्र से है। क्योंकि तब आपको अपनी संरचना पर वैसे भी चलने की ज़रूरत होती है - आपके इच्छित आंतरिक डेटा संरचनाओं पर स्वतंत्र ('यूनिकोड सैंडविच' या केवल बाइट स्ट्रेट)।

क्यों?

यूनिकोड सामान्यीकरण । अनजान के लिए: एक दर्द निवारक दवा ले लो और पढ़ा यह

तो बाइटिज़ रिकर्सियन का उपयोग करके आप एक पत्थर से दो पक्षियों को मारते हैं:

  1. नेस्टेड json डंप से अपने bytestrings जाओ
  2. उपयोगकर्ता इनपुट मूल्यों को सामान्यीकृत करें, ताकि आप अपने भंडारण में सामान ढूंढ सकें।

मेरे परीक्षणों में यह पता चला है कि एक unicodedata.normalize ('NFC', इनपुट) .encode ('utf-8') के साथ input.encode ('utf-8') को बदलना w / o NFC से भी तेज था - लेकिन मुझे लगता है कि नमूना डेटा पर भारी निर्भर करता है।


3

गेटचा वह है simplejsonऔर jsonदो अलग-अलग मॉड्यूल हैं, कम से कम जिस तरह से वे यूनिकोड के साथ व्यवहार करते हैं। आपके पास jsonpy 2.6+ है, और यह आपको यूनिकोड मान देता है, जबकि simplejsonस्ट्रिंग ऑब्जेक्ट देता है। बस अपने वातावरण में easy_install-ing simplejson आज़माएं और देखें कि क्या काम करता है। इसने मेरे लिए किया।


2

डंप और लोड के लिए जस के बजाय सिर्फ अचार का उपयोग करें, जैसे:

    import json
    import pickle

    d = { 'field1': 'value1', 'field2': 2, }

    json.dump(d,open("testjson.txt","w"))

    print json.load(open("testjson.txt","r"))

    pickle.dump(d,open("testpickle.txt","w"))

    print pickle.load(open("testpickle.txt","r"))

इसका उत्पादन होता है (तार और पूर्णांक सही ढंग से संभाले जाते हैं):

    {u'field2': 2, u'field1': u'value1'}
    {'field2': 2, 'field1': 'value1'}

1
एक समाधान के लिए +1 जिसमें अतिरिक्त पैकेज (जैसे याम्ल ) की आवश्यकता नहीं है । लेकिन कभी-कभी - जैसे मेरे मूल मामले में - मुझे JSON में डेटा रखने की आवश्यकता है, इसलिए अचार हमेशा सबसे अच्छा विकल्प नहीं है। इसके अलावा, आप safe_loadYAML में हैं, मुझे नहीं पता कि क्या अचार के लिए कुछ समान है ।
ब्रूटस

1

तो, मैं एक ही समस्या में चला गया हूँ। लगता है कि पहला Google परिणाम क्या था।

क्योंकि मुझे PyGTK को सभी डेटा पास करने की आवश्यकता है, यूनिकोड स्ट्रिंग्स मेरे लिए बहुत उपयोगी नहीं हैं। इसलिए मेरे पास एक और पुनरावर्ती रूपांतरण विधि है। यह वास्तव में टाइपसन JSON रूपांतरण के लिए भी आवश्यक है - json.dump () पायथन ऑब्जेक्ट्स की तरह किसी भी गैर-शाब्दिक पर जमानत देगा। हालांकि प्रमुख अनुक्रमित परिवर्तित नहीं करता है।

# removes any objects, turns unicode back into str
def filter_data(obj):
        if type(obj) in (int, float, str, bool):
                return obj
        elif type(obj) == unicode:
                return str(obj)
        elif type(obj) in (list, tuple, set):
                obj = list(obj)
                for i,v in enumerate(obj):
                        obj[i] = filter_data(v)
        elif type(obj) == dict:
                for i,v in obj.iteritems():
                        obj[i] = filter_data(v)
        else:
                print "invalid object in data, converting to string"
                obj = str(obj) 
        return obj

एकमात्र समस्या जो यहां आ सकती है वह यह है कि यदि आपको यूनिकोड से परिवर्तित शब्दकोश में कुंजियों की आवश्यकता है। हालांकि यह कार्यान्वयन मूल्यों को परिवर्तित कर देगा, लेकिन यह यूनिकोड कुंजियों को बनाए रखता है। यदि आप 'newobj' बनाते हैं, तो newobj [str (i)] = ... का उपयोग करें, और obj = newobj असाइन करें जब आप कर लेंगे, तो कुंजियाँ भी बदल जाएँगी।
नील स्टबलेन

यह कुंजी को परिवर्तित करके समझ या बेहतर के साथ बेहतर हो सकता है। यह भी unidiomatic है; यह दोनों जगह वस्तुओं को उत्परिवर्तित करता है (शब्दकोशों के मामले में) और नया मान लौटाता है, जो पायथन के अंतर्निहित संग्रह विधियों के साथ असंगत है जो या तो वर्तमान वस्तु को म्यूट करते हैं या एक नया लौटाते हैं, लेकिन दोनों नहीं।
मार्क अमेरी

1

मेरे पास एक स्ट्रिंग के रूप में एक JSON था। कुंजी और मूल्य निम्न उदाहरण की तरह यूनिकोड ऑब्जेक्ट थे:

myStringDict = "{u'key':u'value'}"

मैं byteifyस्ट्रिंग का dictउपयोग करके किसी ऑब्जेक्ट का उपयोग करके ऊपर दिए गए फ़ंक्शन का उपयोग कर सकता हूं ast.literal_eval(myStringDict)


आपने जो उदाहरण दिया है, वह JSON का उदाहरण नहीं है। {u'key':u'value'}JSON नहीं है।
मार्क अमेरी

2
मैं पूरी तरह से जानता हूं कि यह JSON नहीं है। इस तरह मेरी पायथन लिपि में इसे एक बाहरी स्रोत से प्राप्त किया गया। अगर यह सीधे तौर पर निम्न उदाहरण में JSON था, तो मुझे समाधान के रूप में चिह्नित बाइट फ़ंक्शन की आवश्यकता नहीं होगी: {"firstName": "John", "lastName": "Doe"}। यह बहुत अच्छा होगा यदि मतदान से पहले आप उत्तर पढ़ें। धन्यवाद।
नर्क

1

समर्थन पायथन 2 और 3 हुक का उपयोग करके ( https://stackoverflow.com/a/33571117/558397 से )

import requests
import six
from six import iteritems

requests.packages.urllib3.disable_warnings()  # @UndefinedVariable
r = requests.get("http://echo.jsontest.com/key/value/one/two/three", verify=False)

def _byteify(data):
    # if this is a unicode string, return its string representation
    if isinstance(data, six.string_types):
        return str(data.encode('utf-8').decode())

    # if this is a list of values, return list of byteified values
    if isinstance(data, list):
        return [ _byteify(item) for item in data ]

    # if this is a dictionary, return dictionary of byteified keys and values
    # but only if we haven't already byteified it
    if isinstance(data, dict):
        return {
            _byteify(key): _byteify(value) for key, value in iteritems(data)
        }
    # if it's anything else, return it in its original form
    return data

w = r.json(object_hook=_byteify)
print(w)

यह दिखाता है:

 {'three': '', 'key': 'value', 'one': 'two'}

0

इस खेल के लिए देर हो चुकी है, लेकिन मैंने इस पुनरावर्ती ढलाईकार का निर्माण किया। यह मेरी जरूरतों के लिए काम करता है और मुझे लगता है कि यह अपेक्षाकृत पूर्ण है। यह आपकी मदद कर सकता है।

def _parseJSON(self, obj):
    newobj = {}

    for key, value in obj.iteritems():
        key = str(key)

        if isinstance(value, dict):
            newobj[key] = self._parseJSON(value)
        elif isinstance(value, list):
            if key not in newobj:
                newobj[key] = []
                for i in value:
                    newobj[key].append(self._parseJSON(i))
        elif isinstance(value, unicode):
            val = str(value)
            if val.isdigit():
                val = int(val)
            else:
                try:
                    val = float(val)
                except ValueError:
                    val = str(val)
            newobj[key] = val

    return newobj

बस इसे एक JSON ऑब्जेक्ट पास करें:

obj = json.loads(content, parse_float=float, parse_int=int)
obj = _parseJSON(obj)

मेरे पास इसे एक वर्ग के निजी सदस्य के रूप में है, लेकिन आप इस विधि को फिर से तैयार कर सकते हैं जैसा कि आप फिट देखते हैं।


मैंने एक समस्या में भाग लिया है जहाँ मैं JSON को पार्स करने की कोशिश कर रहा हूँ और परिणामस्वरूप मैपिंग को ** kwargs के रूप में पास कर रहा हूँ। ऐसा लगता है कि फ़ंक्शन पैरामीटर नाम यूनिकोड नहीं हो सकते हैं, इसलिए आपका _parseJSON फ़ंक्शन बहुत अच्छा है। यदि कोई आसान तरीका है, तो कोई मुझे बता सकता है।
नील स्टबलेन

1
इस कोड में एक समस्या है - आप सूची के टुकड़े में एक पुनरावर्ती कॉल करते हैं, जो कि विफल हो रहा है यदि सूची के तत्व स्वयं शब्दकोशों नहीं हैं।
I82Much

@ I82Much द्वारा वर्णित बग के अलावा, यह भी बुरी तरह से नाम दिया गया है (यह वास्तव में JSON को पार्स नहीं करता है; json.loadsपहले एक कॉल की आवश्यकता है), मनमाने ढंग से बिना किसी स्पष्ट कारण के लिए इन्टर्स को इन्टर्स में बदलने की कोशिश करता है, और कॉपी-और- नहीं है पेस्ट तैयार है।
मार्क अमेरी

0

मैंने वेल्स के _parse_json () को उन मामलों को संभालने के लिए फिर से लिखा है जहाँ पर json ऑब्जेक्ट अपने आप में एक अरै (मेरा उपयोग केस) है।

def _parseJSON(self, obj):
    if isinstance(obj, dict):
        newobj = {}
        for key, value in obj.iteritems():
            key = str(key)
            newobj[key] = self._parseJSON(value)
    elif isinstance(obj, list):
        newobj = []
        for value in obj:
            newobj.append(self._parseJSON(value))
    elif isinstance(obj, unicode):
        newobj = str(obj)
    else:
        newobj = obj
    return newobj

0

यहाँ C: https://github.com/axiros/nested_encode में एक पुनरावर्ती एनकोडर लिखा गया है

Json.loads की तुलना में लगभग 10% "औसत" संरचनाओं के लिए ओवरहेड प्रदर्शन।

python speed.py                                                                                            
  json loads            [0.16sec]: {u'a': [{u'b': [[1, 2, [u'\xd6ster..
  json loads + encoding [0.18sec]: {'a': [{'b': [[1, 2, ['\xc3\x96ster.
  time overhead in percent: 9%

इस टेस्टस्ट्रक्चर का उपयोग करना:

import json, nested_encode, time

s = """
{
  "firstName": "Jos\\u0301",
  "lastName": "Smith",
  "isAlive": true,
  "age": 25,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "\\u00d6sterreich",
    "state": "NY",
    "postalCode": "10021-3100"
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    }
  ],
  "children": [],
  "spouse": null,
  "a": [{"b": [[1, 2, ["\\u00d6sterreich"]]]}]
}
"""


t1 = time.time()
for i in xrange(10000):
    u = json.loads(s)
dt_json = time.time() - t1

t1 = time.time()
for i in xrange(10000):
    b = nested_encode.encode_nested(json.loads(s))
dt_json_enc = time.time() - t1

print "json loads            [%.2fsec]: %s..." % (dt_json, str(u)[:20])
print "json loads + encoding [%.2fsec]: %s..." % (dt_json_enc, str(b)[:20])

print "time overhead in percent: %i%%"  % (100 * (dt_json_enc - dt_json)/dt_json)

0

पायथन 3.6 के साथ, कभी-कभी मैं अभी भी इस समस्या में दौड़ता हूं। उदाहरण के लिए, जब REST API से प्रतिक्रिया मिल रही है और JSON पर प्रतिक्रिया पाठ लोड हो रहा है, तो मुझे अभी भी यूनिकोड के तार मिलते हैं। Json.dumps () का उपयोग करके एक सरल समाधान मिला।

response_message = json.loads(json.dumps(response.text))
print(response_message)

-1

मैं इस समस्या में भी भाग गया, और JSON से निपटने के लिए, मैं एक छोटे लूप के साथ आया जो यूनिकोड कुंजियों को स्ट्रिंग्स में परिवर्तित करता है। ( simplejsonजीएई स्ट्रिंग स्ट्रिंग वापस नहीं करता है।)

obj JSON से डिकोड की गई वस्तु है:

if NAME_CLASS_MAP.has_key(cls):
    kwargs = {}
    for i in obj.keys():
        kwargs[str(i)] = obj[i]
    o = NAME_CLASS_MAP[cls](**kwargs)
    o.save()

kwargsवह है जो मैं GAE एप्लिकेशन के निर्माता के पास जाता हूं (जिसमें unicodeचाबियां पसंद नहीं हैं **kwargs)

वेल्स से समाधान के रूप में मजबूत नहीं है, लेकिन बहुत छोटा है।


-1

मैं से कोड अनुकूलित किया है जवाब के मार्क Amery विशेष रूप से आदेश से छुटकारा पाने के लिए, isinstanceबतख टाइपिंग के पेशेवरों के लिए।

एन्कोडिंग मैन्युअल रूप से किया जाता है और ensure_asciiअक्षम किया जाता है । के लिए अजगर डॉक्स का json.dumpकहना है कि

अगर यह सुनिश्चित करता है कि AS_II सही है (डिफ़ॉल्ट), आउटपुट में सभी गैर- ASCII अक्षर \ uXXX अनुक्रम के साथ बच गए हैं

अस्वीकरण: सिद्धांत में मैंने हंगेरियन भाषा का उपयोग किया। कुछ उल्लेखनीय हंगेरियन-संबंधित चरित्र एनकोडिंग हैं: cp852जैसे कि आईबीएम / ओईएम एन्कोडिंग। डॉस में (कभी कभी के रूप में संदर्भित ascii , गलत तरीके से मुझे लगता है, इस पर निर्भर है कोडपेज सेटिंग), cp1250इस्तेमाल किया जैसे। विंडोज में (कभी-कभी एएनएसआई के रूप में संदर्भित किया जाता है , स्थानीय सेटिंग्स पर निर्भर), और iso-8859-2, कभी-कभी http सर्वर पर उपयोग किया जाता है। परीक्षण पाठ Tüskéshátú kígyóbűvölőको कोल्टई लसज़लो (मूल व्यक्तिगत नाम रूप) के लिए जिम्मेदार ठहराया गया है और विकिपीडिया से लिया गया है

# coding: utf-8
"""
This file should be encoded correctly with utf-8.
"""
import json

def encode_items(input, encoding='utf-8'):
    u"""original from: https://stackoverflow.com/a/13101776/611007
    adapted by SO/u/611007 (20150623)
    >>> 
    >>> ## run this with `python -m doctest <this file>.py` from command line
    >>> 
    >>> txt = u"Tüskéshátú kígyóbűvölő"
    >>> txt2 = u"T\\u00fcsk\\u00e9sh\\u00e1t\\u00fa k\\u00edgy\\u00f3b\\u0171v\\u00f6l\\u0151"
    >>> txt3 = u"uúuutifu"
    >>> txt4 = b'u\\xfauutifu'
    >>> # txt4 shouldn't be 'u\\xc3\\xbauutifu', string content needs double backslash for doctest:
    >>> assert u'\\u0102' not in b'u\\xfauutifu'.decode('cp1250')
    >>> txt4u = txt4.decode('cp1250')
    >>> assert txt4u == u'u\\xfauutifu', repr(txt4u)
    >>> txt5 = b"u\\xc3\\xbauutifu"
    >>> txt5u = txt5.decode('utf-8')
    >>> txt6 = u"u\\u251c\\u2551uutifu"
    >>> there_and_back_again = lambda t: encode_items(t, encoding='utf-8').decode('utf-8')
    >>> assert txt == there_and_back_again(txt)
    >>> assert txt == there_and_back_again(txt2)
    >>> assert txt3 == there_and_back_again(txt3)
    >>> assert txt3.encode('cp852') == there_and_back_again(txt4u).encode('cp852')
    >>> assert txt3 == txt4u,(txt3,txt4u)
    >>> assert txt3 == there_and_back_again(txt5)
    >>> assert txt3 == there_and_back_again(txt5u)
    >>> assert txt3 == there_and_back_again(txt4u)
    >>> assert txt3.encode('cp1250') == encode_items(txt4, encoding='utf-8')
    >>> assert txt3.encode('utf-8') == encode_items(txt5, encoding='utf-8')
    >>> assert txt2.encode('utf-8') == encode_items(txt, encoding='utf-8')
    >>> assert {'a':txt2.encode('utf-8')} == encode_items({'a':txt}, encoding='utf-8')
    >>> assert [txt2.encode('utf-8')] == encode_items([txt], encoding='utf-8')
    >>> assert [[txt2.encode('utf-8')]] == encode_items([[txt]], encoding='utf-8')
    >>> assert [{'a':txt2.encode('utf-8')}] == encode_items([{'a':txt}], encoding='utf-8')
    >>> assert {'b':{'a':txt2.encode('utf-8')}} == encode_items({'b':{'a':txt}}, encoding='utf-8')
    """
    try:
        input.iteritems
        return {encode_items(k): encode_items(v) for (k,v) in input.iteritems()}
    except AttributeError:
        if isinstance(input, unicode):
            return input.encode(encoding)
        elif isinstance(input, str):
            return input
        try:
            iter(input)
            return [encode_items(e) for e in input]
        except TypeError:
            return input

def alt_dumps(obj, **kwargs):
    """
    >>> alt_dumps({'a': u"T\\u00fcsk\\u00e9sh\\u00e1t\\u00fa k\\u00edgy\\u00f3b\\u0171v\\u00f6l\\u0151"})
    '{"a": "T\\xc3\\xbcsk\\xc3\\xa9sh\\xc3\\xa1t\\xc3\\xba k\\xc3\\xadgy\\xc3\\xb3b\\xc5\\xb1v\\xc3\\xb6l\\xc5\\x91"}'
    """
    if 'ensure_ascii' in kwargs:
        del kwargs['ensure_ascii']
    return json.dumps(encode_items(obj), ensure_ascii=False, **kwargs)

मैं भी हाइलाइट करना चाहते हैं जवाब की Jarret हार्डी जो संदर्भ JSON कल्पना , उद्धृत:

एक स्ट्रिंग शून्य या अधिक यूनिकोड वर्णों का एक संग्रह है

मेरे उपयोग-मामले में मेरे पास जसन के साथ फाइलें थीं। वे utf-8एनकोडेड फाइलें हैं। ensure_asciiपरिणाम ठीक से बच गए लेकिन बहुत पठनीय जोंस फाइलें नहीं हैं, यही कारण है कि मैंने अपनी जरूरतों के हिसाब से मार्क अमेरी के जवाब को अनुकूलित किया है।

सिद्धांत विशेष रूप से विचारशील नहीं है, लेकिन मैं इस उम्मीद में कोड साझा करता हूं कि यह किसी के लिए उपयोगी होगा।


मुझे यकीन नहीं है कि मैं यहाँ बतख टाइपिंग के लाभ देख सकता हूँ? हम जानते हैं कि संग्रह से लौटे संग्रह json.loadsसूचियों या dicts होने जा रहे हैं, न कि कुछ उपयोगकर्ता-परिभाषित या पुस्तकालय-परिभाषित प्रकार जो अपने तरीकों और जादू विधियों को लागू करते हैं, इसलिए सिर्फ एक isinstanceचेक क्यों नहीं ? क्या यह अस्तित्व के लिए जाँचने से आसान नहीं है iteritemsया क्या iterवस्तु को एक तर्क के रूप में स्वीकार किया जाएगा?
मार्क एमी

@ मार्की यह डंप के बारे में है, भार नहीं। यदि आप डंप करने के लिए डेटा बनाते हैं - इसे लोड करने के विपरीत - आप सुनिश्चित नहीं कर सकते कि यह क्या है। विचार यह था कि इसे कोड में कहीं से भी आने दिया जाए।
n611x007 7

-2

की जाँच करें इस इस तरह एक ऐसी ही सवाल है कि कहा गया है का जवाब

U- उपसर्ग का अर्थ है कि आपके पास एक यूनिकोड स्ट्रिंग है। जब आप वास्तव में स्ट्रिंग का उपयोग करते हैं, तो यह आपके डेटा में दिखाई नहीं देगा। मुद्रित आउटपुट द्वारा फेंका नहीं जाना चाहिए।

उदाहरण के लिए, इसे आज़माएँ:

print mail_accounts[0]["i"]

आप एक यू नहीं देखेंगे


सच नहीं है, उदाहरण के लिए यदि आप एक यूनिकोड स्ट्रिंग युक्त कुछ को स्वरूपित करना चाहते हैं, तो Py2 में। उदाहरण के लिए '{}'.format({u'x' : u'y'})अभी भी यू शामिल हैं।
पोंकडूडल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.