JSON डेटा को पायथन ऑब्जेक्ट में कैसे परिवर्तित करें


281

मैं JSON डेटा को पायथन ऑब्जेक्ट में परिवर्तित करने के लिए पायथन का उपयोग करना चाहता हूं।

मुझे फेसबुक एपीआई से JSON डेटा ऑब्जेक्ट प्राप्त होते हैं, जिसे मैं अपने डेटाबेस में संग्रहीत करना चाहता हूं।

Django (पायथन) में मेरा वर्तमान दृश्य ( request.POSTJSON शामिल है):

response = request.POST
user = FbApiUser(user_id = response['id'])
user.name = response['name']
user.username = response['username']
user.save()
  • यह ठीक काम करता है, लेकिन मैं जटिल JSON डेटा ऑब्जेक्ट कैसे संभाल सकता हूं?

  • अगर मैं किसी भी तरह इस JSON ऑब्जेक्ट को आसान उपयोग के लिए पायथन ऑब्जेक्ट में परिवर्तित कर सकता हूं तो क्या यह ज्यादा बेहतर नहीं होगा?


आमतौर पर JSON वेनिला सूचियों या डाइक में परिवर्तित हो जाता है। क्या तुम यही चाहते हो? या क्या आप JSON को सीधे कस्टम प्रकार में बदलने की उम्मीद कर रहे हैं?
शककाई ५’११ ’सुबह .:०१

मैं इसे एक वस्तु में बदलना चाहता हूं, जिसे मैं "का उपयोग करके एक्सेस कर सकता हूं।" । उपरोक्त उदाहरण से -> reponse.name, response.education.id आदि ....
साईं कृष्णा

44
dictS का उपयोग ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग करने के लिए एक कमजोर-सॉस तरीका है। आपके कोड के पाठकों के लिए अपेक्षाओं को संप्रेषित करने के लिए शब्दकोश एक बहुत ही खराब तरीका है। शब्दकोश का उपयोग करते हुए, आप स्पष्ट रूप से और पुन: कैसे निर्दिष्ट कर सकते हैं कि कुछ शब्दकोश कुंजी-मूल्य जोड़े आवश्यक हैं, जबकि अन्य नहीं हैं? इस बात की पुष्टि करने के बारे में कि किसी दिए गए मूल्य स्वीकार्य सीमा या सेट में है? उन कार्यों के बारे में जो उस प्रकार के ऑब्जेक्ट के लिए विशिष्ट हैं जो आप (उर्फ तरीकों) के साथ काम कर रहे हैं? शब्दकोश आसान और बहुमुखी हैं, लेकिन बहुत से देव ऐसे कार्य करते हैं जैसे वे भूल गए कि पायथन एक कारण के लिए एक वस्तु उन्मुख भाषा है।
स्टू 20

1
इस github.com/jsonpickle/jsonpickle के लिए एक अजगर पुस्तकालय है (टिप्पणी चूंकि उत्तर धागा में बहुत नीचे है और अभेद्य होना चाहिए।)
शुभकामनाएं

जवाबों:


355

आप इसे एक लाइन में, उपयोग कर सकते हैं namedtupleऔर object_hook:

import json
from collections import namedtuple

data = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'

# Parse JSON into an object with attributes corresponding to dict keys.
x = json.loads(data, object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))
print x.name, x.hometown.name, x.hometown.id

या, इसे आसानी से पुन: उपयोग करने के लिए:

def _json_object_hook(d): return namedtuple('X', d.keys())(*d.values())
def json2obj(data): return json.loads(data, object_hook=_json_object_hook)

x = json2obj(data)

आप इसे, कुंजी है कि अच्छी विशेषता नाम नहीं हैं संभाल की जाँच करना चाहते हैं namedtupleके renameपैरामीटर


8
इससे मान में त्रुटि हो सकती है, ValueError: नाम और फ़ील्ड नाम एक संख्या के साथ शुरू नहीं हो सकते: '123'
PvdL

3
पायथन के लिए एक नौसिखिया के रूप में, मुझे दिलचस्पी है अगर यह एक बचत चीज भी है जब सुरक्षा एक मुद्दा है।
बेंजिस्ट

8
यह हर बार पार्सिंग करते समय JSON ऑब्जेक्ट का सामना करते हुए एक नया अलग वर्ग बनाता है , है ना?
fikr4n

2
दिलचस्प। मैंने सोचा था कि उसी क्रम में भरोसा करना d.keys()और d.values()पुनरावृति की गारंटी नहीं है, लेकिन मैं गलत था। डॉक्स कहते हैं: "कुंजी, मूल्यों और आइटम विचारों शब्दकोश में कोई हस्तक्षेप संशोधनों के साथ खत्म हो गया दोहराया रहे हैं, तो आइटम के आदेश सीधे अनुरूप होगा।"। ऐसे छोटे, स्थानीय कोड ब्लॉक के लिए जानकर अच्छा लगा। मैं इस तरह की निर्भरता के कोड के स्पष्ट रूप से सतर्क अनुरक्षकों के लिए एक टिप्पणी जोड़ूंगा।
cfi

1
मैं किसी भी अच्छे सामान्य प्रयोजन के रिवर्स ऑपरेशन से अवगत नहीं हूं। किसी भी व्यक्तिगत नामपट्ट का उपयोग करके एक तानाशाही में बदल दिया जा सकता है x._asdict(), जो साधारण मामलों के लिए मदद कर सकता है।
डी.एस.

127

मॉड्यूल प्रलेखन में सक्रिय JSON ऑब्जेक्ट डिकोडिंग शीर्षक वाला अनुभाग देखें । आप एक विशिष्ट पायथन प्रकार में JSON ऑब्जेक्ट को डीकोड करने के लिए उपयोग कर सकते हैं।json

यहाँ एक उदाहरण है:

class User(object):
    def __init__(self, name, username):
        self.name = name
        self.username = username

import json
def object_decoder(obj):
    if '__type__' in obj and obj['__type__'] == 'User':
        return User(obj['name'], obj['username'])
    return obj

json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}',
           object_hook=object_decoder)

print type(User)  # -> <type 'type'>

अपडेट करें

यदि आप json मॉड्यूल के माध्यम से किसी डिक्शनरी में डेटा एक्सेस करना चाहते हैं, तो यह करें:

user = json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}')
print user['name']
print user['username']

एक नियमित शब्दकोश की तरह।


1
अरे, मैं अभी पढ़ रहा था और मुझे एहसास हुआ कि डिक्शनरी पूरी तरह से करेगी, केवल मैं सोच रहा था कि JSON ऑब्जेक्ट्स को डिक्शनरी में कैसे कन्वर्ट किया जाए और मैं इस डेटा को डिक्शनरी से कैसे एक्सेस करूं?
साईं कृष्णा

बहुत बढ़िया, यह लगभग स्पष्ट है, बस एक और छोटी बात जानना चाहता था कि अगर यह वस्तु है -> {'शिक्षा': {'name1': 456, 'name2': 567}}, मैं इस डेटा का उपयोग कैसे करूं?
साईं कृष्णा

यह सिर्फ topLvelData ['शिक्षा'] ['name1'] ==> 456 होगा। समझ में आता है?
:

1
@ पता: मुझे लगता है कि आपकी टिप्पणी अनुचित है। वर्तमान में सभी उत्तरों में से यह कक्षाओं को सही करने के लिए एकमात्र है। जिसका अर्थ है: यह एक-पास ऑपरेशन है और परिणाम सही प्रकार का उपयोग करता है। अचार ही JSON (बाइनरी बनाम टेक्सुअल रेप) की तुलना में अलग-अलग अनुप्रयोगों के लिए है और jsonpickle एक अमानक काम है। मुझे यह देखने में दिलचस्पी होगी कि आप इस मुद्दे को कैसे सुलझाते हैं कि std json lib ऊपरी हुक ट्री को ऑब्जेक्ट हुक के लिए प्रदान नहीं करता है
cfi

मुझे इस पर @Ben से सहमत होना होगा। यह वास्तव में बुरा समाधान है। स्केलेबल बिल्कुल नहीं। आपको फ़ील्ड के नाम स्ट्रिंग और फ़ील्ड के रूप में बनाए रखने की आवश्यकता होगी। यदि आप अपने क्षेत्रों को फिर से भरना चाहते हैं तो डिकोडिंग विफल हो जाएगी (निश्चित रूप से पहले से ही क्रमबद्ध डेटा अब वैसे भी प्रासंगिक नहीं होगा)। इसी अवधारणा को पहले से ही jsonpickle के
मर्दाद

98

यह कोड गोल्फ नहीं है, लेकिन यहां types.SimpleNamespaceJSON ऑब्जेक्ट्स के लिए कंटेनर के रूप में उपयोग करते हुए, मेरी सबसे छोटी चाल है।

अग्रणी namedtupleसमाधान की तुलना में , यह है:

  • शायद अधिक तेज़ / छोटा क्योंकि यह प्रत्येक ऑब्जेक्ट के लिए एक वर्ग नहीं बनाता है
  • कम
  • कोई renameविकल्प नहीं है, और संभवतया मान्य पहचानकर्ता नहीं हैं ( setattrकवर के तहत उपयोग करता है ) पर समान सीमा

उदाहरण:

from __future__ import print_function
import json

try:
    from types import SimpleNamespace as Namespace
except ImportError:
    # Python 2.x fallback
    from argparse import Namespace

data = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'

x = json.loads(data, object_hook=lambda d: Namespace(**d))

print (x.name, x.hometown.name, x.hometown.id)

2
वैसे, सीरियलाइज़ेशन लाइब्रेरी मार्शमैलो अपने @post_loadसज्जाकार के साथ एक समान सुविधा प्रदान करती है । marshmallow.readthedocs.io/en/latest/…
टेलर एड्मिस्टन

3
अर्गपर्स पर निर्भरता से बचने के लिए: अर्गपार्स आयात को प्रतिस्थापित करें from types import SimpleNamespaceऔर उपयोग करें:x = json.loads(data, object_hook=lambda d: SimpleNamespace(**d))
मैक्सक्लेपज़िग

8
यह सबसे सुरुचिपूर्ण समाधान है, शीर्ष पर होना चाहिए।
ScalaWilliam

4
पायथन 3.x के तहत चलने पर @ maxschlepzig के समाधान का उपयोग करने के लिए संपादित किया गया ( types.SimpleNamespace2.7 में मौजूद नहीं है, दुर्भाग्य से)।
डैन लेन्स्की

1
क्यों print_function?
chwi

90

आप यह कोशिश कर सकते हैं:

class User(object):
    def __init__(self, name, username, *args, **kwargs):
        self.name = name
        self.username = username

import json
j = json.loads(your_json)
u = User(**j)

बस एक नई वस्तु बनाएं, और नक्शे के रूप में मापदंडों को पास करें।


1
मुझे टाइपर्रर मिलता है: 'यूजर' ऑब्जेक्ट सब्स्क्राइब्ड नहीं है
मेहदी

1
यह स्वीकृत उत्तर होना चाहिए। मेरे लिए काम बाकी सभी की तुलना में बहुत सरल है।
इज़िक

मैंने * args, ** kwargs का उपयोग नहीं किया, लेकिन समाधान ने काम किया।
मलकवियानो

1
उपयोगकर्ता (** j) का कहना है कि यह नाम और उपयोगकर्ता नाम मापदंडों को याद कर रहा है, यह भी कि कैसे हुकुम को आरंभिक रूप दिया जाता है?
एरोन स्टेनबैक

40

यहाँ एक त्वरित और गंदा जूस अचार विकल्प है

import json

class User:
    def __init__(self, name, username):
        self.name = name
        self.username = username

    def to_json(self):
        return json.dumps(self.__dict__)

    @classmethod
    def from_json(cls, json_str):
        json_dict = json.loads(json_str)
        return cls(**json_dict)

# example usage
User("tbrown", "Tom Brown").to_json()
User.from_json(User("tbrown", "Tom Brown").to_json()).to_json()

1
यह अच्छा तरीका नहीं है। पहली बार to_json और from_json को आपकी कक्षा में नहीं रखा जाना चाहिए। दूसरे स्थान पर यह नेस्टेड वर्गों के लिए काम नहीं करेगा।
जुरास

17

जटिल वस्तुओं के लिए, आप JSON अचार का उपयोग कर सकते हैं

JSON में किसी भी मनमानी वस्तु ग्राफ को क्रमबद्ध करने के लिए पायथन लाइब्रेरी। यह लगभग किसी भी पायथन ऑब्जेक्ट को ले जा सकता है और ऑब्जेक्ट को JSON में बदल सकता है। इसके अतिरिक्त, यह ऑब्जेक्ट को पाइथन में वापस ला सकता है।


6
मुझे लगता है कि jsonstruct बेहतर है। jsonstruct originally a fork of jsonpickle (Thanks guys!). The key difference between this library and jsonpickle is that during deserialization, jsonpickle requires Python types to be recorded as part of the JSON. This library intends to remove this requirement, instead, requires a class to be passed in as an argument so that its definition can be inspected. It will then return an instance of the given class. This approach is similar to how Jackson (of Java) works.
अभिषेक गुप्ता

3
Jsonstruct के साथ समस्या यह है कि इसे बनाए रखा जाना प्रतीत नहीं होता है (वास्तव में, यह परित्यक्त दिखता है) और यह वस्तुओं की सूची में परिवर्तित करने में विफल रहता है, जैसे '[{"name":"object1"},{"name":"object2"}]'। jsonpickle इसे बहुत अच्छी तरह से हैंडल नहीं करता है, या तो।
एलएस

1
मुझे नहीं पता कि इस जवाब को अधिक वोट क्यों नहीं मिल रहे हैं। अधिकांश अन्य समाधान काफी बाहर हैं। किसी ने JSON डे / क्रमांकन के लिए एक महान पुस्तकालय विकसित किया - इसका उपयोग क्यों नहीं किया? इसके अलावा, सूचियों के साथ ठीक काम कर रहा है - यह @LS के साथ आपका मुद्दा क्या था?
19

1
@guyarad, समस्या यह है: x = jsonpickle.d timecode ('[{"नाम": "object1"}, {"name": "object2"}]) शब्दकोशों की एक सूची देता है ([{' name ') object1 '}, {' name ':' object2 '}]), गुणों वाली वस्तुओं की सूची नहीं (x [0] .name ==' object1 '), जो कि मूल प्रश्न की आवश्यकता है। यह पाने के लिए, मैं eddygeek द्वारा सुझाए गए object_hook / Namespace दृष्टिकोण का उपयोग करके समाप्त हुआ, लेकिन ubershmekel द्वारा त्वरित / गंदा दृष्टिकोण बहुत अच्छा लगता है। मुझे लगता है कि मैं jsonpickle के set_encoder_options () (undocumented!) के साथ object_hook का उपयोग कर सकता हूं, लेकिन यह मूल json मॉड्यूल की तुलना में अधिक कोड लेगा। मुझे गलत साबित होना अच्छा लगेगा!
एलएस

@LS यदि आपके पास इनपुट पर कोई नियंत्रण नहीं है, जो वास्तव में ओपी ने पूछा है, तो jsonpickle आदर्श नहीं है क्योंकि यह प्रत्येक स्तर में वास्तविक प्रकार की उम्मीद करता है (और लापता होने पर बुनियादी प्रकारों को ग्रहण करेगा)। दोनों समाधान "प्यारा" हैं।
मसराद

12

यदि आप Python 3.5+ का उपयोग कर रहे हैं, तो आप jsonsपुराने पुराने पायथन ऑब्जेक्ट्स को क्रमबद्ध और असाध्य बनाने के लिए उपयोग कर सकते हैं :

import jsons

response = request.POST

# You'll need your class attributes to match your dict keys, so in your case do:
response['id'] = response.pop('user_id')

# Then you can load that dict into your class:
user = jsons.load(response, FbApiUser)

user.save()

आप अधिक लालित्य के लिए FbApiUserविरासत भी बना सकते हैं jsons.JsonSerializable:

user = FbApiUser.from_json(response)

ये उदाहरण काम करेंगे यदि आपकी कक्षा में पायथन डिफ़ॉल्ट प्रकार होते हैं, जैसे कि तार, पूर्णांक, सूचियाँ, डेटाटाइम्स, आदि, jsonsहालांकि कस्टम प्रकार के लिए लिब की आवश्यकता होगी।


7

यदि आप अजगर 3.6+ का उपयोग कर रहे हैं, तो आप मार्शमॉलो-डेटाक्लास का उपयोग कर सकते हैं । उपरोक्त सूचीबद्ध सभी समाधानों के विपरीत, यह सरल और सुरक्षित दोनों प्रकार है:

from marshmallow_dataclass import dataclass

@dataclass
class User:
    name: str

user, err = User.Schema().load({"name": "Ramirez"})

TypeError: make_data_class() got an unexpected keyword argument 'many'
जोहान


6

Lovasoa के बहुत अच्छे जवाब में सुधार।

यदि आप अजगर 3.6+ का उपयोग कर रहे हैं, तो आप उपयोग कर सकते हैं:
pip install marshmallow-enumऔर
pip install marshmallow-dataclass

इसका सरल और प्रकार सुरक्षित है।

आप अपनी कक्षा को स्ट्रिंग-जसन में बदल सकते हैं और इसके विपरीत:

वस्तु से स्ट्रिंग जोंस तक:

    from marshmallow_dataclass import dataclass
    user = User("Danilo","50","RedBull",15,OrderStatus.CREATED)
    user_json = User.Schema().dumps(user)
    user_json_str = user_json.data

स्ट्रिंग जसन से वस्तु तक:

    json_str = '{"name":"Danilo", "orderId":"50", "productName":"RedBull", "quantity":15, "status":"Created"}'
    user, err = User.Schema().loads(json_str)
    print(user,flush=True)

कक्षा परिभाषाएँ:

class OrderStatus(Enum):
    CREATED = 'Created'
    PENDING = 'Pending'
    CONFIRMED = 'Confirmed'
    FAILED = 'Failed'

@dataclass
class User:
    def __init__(self, name, orderId, productName, quantity, status):
        self.name = name
        self.orderId = orderId
        self.productName = productName
        self.quantity = quantity
        self.status = status

    name: str
    orderId: str
    productName: str
    quantity: int
    status: OrderStatus

1
आपको कंस्ट्रक्टर की ज़रूरत नहीं है, बस init पास करें = डेटाकॉल के लिए सही है और आप जाने के लिए अच्छे हैं।
जोसेफ कोरबेल

5

मैंने any2any नामक एक छोटा (डी) क्रमांकन ढांचा लिखा है जो दो पायथन प्रकारों के बीच जटिल रूपांतरण करने में मदद करता है।

आपके मामले में, मुझे लगता है कि आप एक शब्दकोश (एक से प्राप्त json.loads) से एक जटिल वस्तु response.education ; response.name, एक नेस्टेड संरचना response.education.id, आदि के साथ बदलना चाहते हैं ... तो ठीक यही बात इस रूपरेखा के लिए बनाई गई है। प्रलेखन अभी तक महान नहीं है, लेकिन उपयोग करके any2any.simple.MappingToObject, आपको बहुत आसानी से ऐसा करने में सक्षम होना चाहिए। कृपया बताएं यदि आपको मदद की जरूरत है।


Sebpiq, any2any स्थापित किया है और विधि कॉल के इच्छित अनुक्रम को समझने में परेशानी हो रही है। क्या आप प्रत्येक कुंजी के लिए एक प्रॉपर्टी के साथ एक पायथन ऑब्जेक्ट में डिक्शनरी का एक सरल उदाहरण दे सकते हैं?
संजोए

हाय @sansjoe! यदि आपने इसे पीपीआई से स्थापित किया है, तो संस्करण पूरी तरह से पुराना है, मैंने कुछ सप्ताह पहले पूरी तरह से रिफैक्टिंग बनाया है। आपको
जीथब

मैंने इसे pypy से स्थापित किया क्योंकि github ने pypy से इसे स्थापित करने के लिए कहा था। इसके अलावा, आप ने कहा PyPy पहले की तारीख महीनों से बाहर था .. यह काम नहीं किया :( मैं एक बग रिपोर्ट दायर यद्यपि! Github.com/sebpiq/any2any/issues/11
sneilan

4

चूंकि किसी ने मेरा जैसा जवाब दिया, इसलिए मैं इसे यहां पोस्ट करने जा रहा हूं।

यह एक मजबूत वर्ग है जो आसानी से जसन के बीच आगे-पीछे हो सकता है strऔर dictजिसे मैंने अपने उत्तर से दूसरे प्रश्न में कॉपी कर लिया है :

import json

class PyJSON(object):
    def __init__(self, d):
        if type(d) is str:
            d = json.loads(d)

        self.from_dict(d)

    def from_dict(self, d):
        self.__dict__ = {}
        for key, value in d.items():
            if type(value) is dict:
                value = PyJSON(value)
            self.__dict__[key] = value

    def to_dict(self):
        d = {}
        for key, value in self.__dict__.items():
            if type(value) is PyJSON:
                value = value.to_dict()
            d[key] = value
        return d

    def __repr__(self):
        return str(self.to_dict())

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __getitem__(self, key):
        return self.__dict__[key]

json_str = """... json string ..."""

py_json = PyJSON(json_str)

2

एक फ़ाइल से लोड करने के लिए @DS प्रतिक्रिया को थोड़ा संशोधित करना:

def _json_object_hook(d): return namedtuple('X', d.keys())(*d.values())
def load_data(file_name):
  with open(file_name, 'r') as file_data:
    return file_data.read().replace('\n', '')
def json2obj(file_name): return json.loads(load_data(file_name), object_hook=_json_object_hook)

एक बात: यह आगे की संख्या के साथ आइटम लोड नहीं कर सकता। ऐशे ही:

{
  "1_first_item": {
    "A": "1",
    "B": "2"
  }
}

क्योंकि "1_first_item" एक मान्य अजगर क्षेत्र का नाम नहीं है।


2

समाधान खोजते समय, मैंने इस ब्लॉग पोस्ट पर ठोकर खाई है: https://blog.mosthege.net/2016/11/12/json-deserialization-of-nested-objects/

यह उसी तकनीक का उपयोग करता है जैसा कि पिछले उत्तरों में बताया गया है लेकिन सज्जाकारों के उपयोग के साथ। एक और बात जो मुझे उपयोगी लगी वह यह है कि यह डायरियालेशन के अंत में एक टाइप की गई वस्तु को लौटाता है

class JsonConvert(object):
    class_mappings = {}

    @classmethod
    def class_mapper(cls, d):
        for keys, cls in clsself.mappings.items():
            if keys.issuperset(d.keys()):   # are all required arguments present?
                return cls(**d)
        else:
            # Raise exception instead of silently returning None
            raise ValueError('Unable to find a matching class for object: {!s}'.format(d))

    @classmethod
    def complex_handler(cls, Obj):
        if hasattr(Obj, '__dict__'):
            return Obj.__dict__
        else:
            raise TypeError('Object of type %s with value of %s is not JSON serializable' % (type(Obj), repr(Obj)))

    @classmethod
    def register(cls, claz):
        clsself.mappings[frozenset(tuple([attr for attr,val in cls().__dict__.items()]))] = cls
        return cls

    @classmethod
    def to_json(cls, obj):
        return json.dumps(obj.__dict__, default=cls.complex_handler, indent=4)

    @classmethod
    def from_json(cls, json_str):
        return json.loads(json_str, object_hook=cls.class_mapper)

उपयोग:

@JsonConvert.register
class Employee(object):
    def __init__(self, Name:int=None, Age:int=None):
        self.Name = Name
        self.Age = Age
        return

@JsonConvert.register
class Company(object):
    def __init__(self, Name:str="", Employees:[Employee]=None):
        self.Name = Name
        self.Employees = [] if Employees is None else Employees
        return

company = Company("Contonso")
company.Employees.append(Employee("Werner", 38))
company.Employees.append(Employee("Mary"))

as_json = JsonConvert.to_json(company)
from_json = JsonConvert.from_json(as_json)
as_json_from_json = JsonConvert.to_json(from_json)

assert(as_json_from_json == as_json)

print(as_json_from_json)

2

डीएस के उत्तर पर थोड़ा विस्तार करना, अगर आपको वस्तु को परस्पर (जो नामांकित नहीं है) होने की आवश्यकता है, तो आप नामपट्ट के बजाय रिकॉर्डक्लास लाइब्रेरी का उपयोग कर सकते हैं :

import json
from recordclass import recordclass

data = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'

# Parse into a mutable object
x = json.loads(data, object_hook=lambda d: recordclass('X', d.keys())(*d.values()))

संशोधित वस्तु को सिंपलसन के उपयोग से बहुत आसानी से वापस जसन में परिवर्तित किया जा सकता है :

x.name = "John Doe"
new_json = simplejson.dumps(x)

1

यदि आप पायथन 3.6 या नए का उपयोग कर रहे हैं, तो आप स्क्वेमा पर एक नज़र डाल सकते हैं - सांख्यिकीय रूप से टाइप किए गए डेटा संरचनाओं के लिए एक हल्का मॉड्यूल। बिना अतिरिक्त काम के साधारण डेटा सत्यापन, रूपांतरण और क्रमांकन प्रदान करते हुए आपके कोड को पढ़ना आसान बनाता है। आप इसे नेमटुपल्स और डेटाक्लासेस के अधिक परिष्कृत और विचारशील विकल्प के रूप में सोच सकते हैं। यहां बताया गया है कि आप इसका उपयोग कैसे कर सकते हैं:

from uuid import UUID
from squema import Squema


class FbApiUser(Squema):
    id: UUID
    age: int
    name: str

    def save(self):
        pass


user = FbApiUser(**json.loads(response))
user.save()

यह भी करने के लिए JVM भाषा के तरीकों के समान है।
जावदबा

1

मैं एक ऐसे समाधान की खोज कर रहा था recordclass.RecordClass, जिसमें काम किया गया हो , नेस्टेड वस्तुओं का समर्थन करता है और json क्रमांकन और json deserialization दोनों के लिए काम करता है।

डीएस के जवाब पर विस्तार, और बेनेस्ट्र से समाधान पर विस्तार, मैं निम्नलिखित के साथ आया था जो काम करने लगता है:

कोड:

import json
import recordclass

class NestedRec(recordclass.RecordClass):
    a : int = 0
    b : int = 0

class ExampleRec(recordclass.RecordClass):
    x : int       = None
    y : int       = None
    nested : NestedRec = NestedRec()

class JsonSerializer:
    @staticmethod
    def dumps(obj, ensure_ascii=True, indent=None, sort_keys=False):
        return json.dumps(obj, default=JsonSerializer.__obj_to_dict, ensure_ascii=ensure_ascii, indent=indent, sort_keys=sort_keys)

    @staticmethod
    def loads(s, klass):
        return JsonSerializer.__dict_to_obj(klass, json.loads(s))

    @staticmethod
    def __obj_to_dict(obj):
        if hasattr(obj, "_asdict"):
            return obj._asdict()
        else:
            return json.JSONEncoder().default(obj)

    @staticmethod
    def __dict_to_obj(klass, s_dict):
        kwargs = {
            key : JsonSerializer.__dict_to_obj(cls, s_dict[key]) if hasattr(cls,'_asdict') else s_dict[key] \
                for key,cls in klass.__annotations__.items() \
                    if s_dict is not None and key in s_dict
        }
        return klass(**kwargs)

उपयोग:

example_0 = ExampleRec(x = 10, y = 20, nested = NestedRec( a = 30, b = 40 ) )

#Serialize to JSON

json_str = JsonSerializer.dumps(example_0)
print(json_str)
#{
#  "x": 10,
#  "y": 20,
#  "nested": {
#    "a": 30,
#    "b": 40
#  }
#}

# Deserialize from JSON
example_1 = JsonSerializer.loads(json_str, ExampleRec)
example_1.x += 1
example_1.y += 1
example_1.nested.a += 1
example_1.nested.b += 1

json_str = JsonSerializer.dumps(example_1)
print(json_str)
#{
#  "x": 11,
#  "y": 21,
#  "nested": {
#    "a": 31,
#    "b": 41
#  }
#}

1

यहां दिए गए उत्तर सही ऑब्जेक्ट प्रकार को वापस नहीं करते हैं, इसलिए मैंने नीचे इन विधियों को बनाया है। यदि आप दिए गए JSON में मौजूद वर्ग के लिए अधिक फ़ील्ड जोड़ने का प्रयास करते हैं तो वे भी विफल हो जाते हैं:

def dict_to_class(class_name: Any, dictionary: dict) -> Any:
    instance = class_name()
    for key in dictionary.keys():
        setattr(instance, key, dictionary[key])
    return instance


def json_to_class(class_name: Any, json_string: str) -> Any:
    dict_object = json.loads(json_string)
    return dict_to_class(class_name, dict_object)

0

Python3.x

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

हालाँकि यह एक CoDec है।

थोड़े और काम से आप अपनी कक्षा का निर्माण अन्य तरीकों से कर सकते हैं। मैं इसे बनाने के लिए एक डिफॉल्ट कंस्ट्रक्टर मान लेता हूं, फिर मैं वर्ग को अपडेट करता हूं।

import json
import collections


class JsonClassSerializable(json.JSONEncoder):

    REGISTERED_CLASS = {}

    def register(ctype):
        JsonClassSerializable.REGISTERED_CLASS[ctype.__name__] = ctype

    def default(self, obj):
        if isinstance(obj, collections.Set):
            return dict(_set_object=list(obj))
        if isinstance(obj, JsonClassSerializable):
            jclass = {}
            jclass["name"] = type(obj).__name__
            jclass["dict"] = obj.__dict__
            return dict(_class_object=jclass)
        else:
            return json.JSONEncoder.default(self, obj)

    def json_to_class(self, dct):
        if '_set_object' in dct:
            return set(dct['_set_object'])
        elif '_class_object' in dct:
            cclass = dct['_class_object']
            cclass_name = cclass["name"]
            if cclass_name not in self.REGISTERED_CLASS:
                raise RuntimeError(
                    "Class {} not registered in JSON Parser"
                    .format(cclass["name"])
                )
            instance = self.REGISTERED_CLASS[cclass_name]()
            instance.__dict__ = cclass["dict"]
            return instance
        return dct

    def encode_(self, file):
        with open(file, 'w') as outfile:
            json.dump(
                self.__dict__, outfile,
                cls=JsonClassSerializable,
                indent=4,
                sort_keys=True
            )

    def decode_(self, file):
        try:
            with open(file, 'r') as infile:
                self.__dict__ = json.load(
                    infile,
                    object_hook=self.json_to_class
                )
        except FileNotFoundError:
            print("Persistence load failed "
                  "'{}' do not exists".format(file)
                  )


class C(JsonClassSerializable):

    def __init__(self):
        self.mill = "s"


JsonClassSerializable.register(C)


class B(JsonClassSerializable):

    def __init__(self):
        self.a = 1230
        self.c = C()


JsonClassSerializable.register(B)


class A(JsonClassSerializable):

    def __init__(self):
        self.a = 1
        self.b = {1, 2}
        self.c = B()

JsonClassSerializable.register(A)

A().encode_("test")
b = A()
b.decode_("test")
print(b.a)
print(b.b)
print(b.c.a)

संपादित करें

कुछ और शोधों के साथ, मुझे एक मेटाक्लर का उपयोग करके SUPERCLASS रजिस्टर विधि कॉल की आवश्यकता के बिना सामान्यीकरण करने का एक तरीका मिला।

import json
import collections

REGISTERED_CLASS = {}

class MetaSerializable(type):

    def __call__(cls, *args, **kwargs):
        if cls.__name__ not in REGISTERED_CLASS:
            REGISTERED_CLASS[cls.__name__] = cls
        return super(MetaSerializable, cls).__call__(*args, **kwargs)


class JsonClassSerializable(json.JSONEncoder, metaclass=MetaSerializable):

    def default(self, obj):
        if isinstance(obj, collections.Set):
            return dict(_set_object=list(obj))
        if isinstance(obj, JsonClassSerializable):
            jclass = {}
            jclass["name"] = type(obj).__name__
            jclass["dict"] = obj.__dict__
            return dict(_class_object=jclass)
        else:
            return json.JSONEncoder.default(self, obj)

    def json_to_class(self, dct):
        if '_set_object' in dct:
            return set(dct['_set_object'])
        elif '_class_object' in dct:
            cclass = dct['_class_object']
            cclass_name = cclass["name"]
            if cclass_name not in REGISTERED_CLASS:
                raise RuntimeError(
                    "Class {} not registered in JSON Parser"
                    .format(cclass["name"])
                )
            instance = REGISTERED_CLASS[cclass_name]()
            instance.__dict__ = cclass["dict"]
            return instance
        return dct

    def encode_(self, file):
        with open(file, 'w') as outfile:
            json.dump(
                self.__dict__, outfile,
                cls=JsonClassSerializable,
                indent=4,
                sort_keys=True
            )

    def decode_(self, file):
        try:
            with open(file, 'r') as infile:
                self.__dict__ = json.load(
                    infile,
                    object_hook=self.json_to_class
                )
        except FileNotFoundError:
            print("Persistence load failed "
                  "'{}' do not exists".format(file)
                  )


class C(JsonClassSerializable):

    def __init__(self):
        self.mill = "s"


class B(JsonClassSerializable):

    def __init__(self):
        self.a = 1230
        self.c = C()


class A(JsonClassSerializable):

    def __init__(self):
        self.a = 1
        self.b = {1, 2}
        self.c = B()


A().encode_("test")
b = A()
b.decode_("test")
print(b.a)
# 1
print(b.b)
# {1, 2}
print(b.c.a)
# 1230
print(b.c.c.mill)
# s

0

आप उपयोग कर सकते हैं

x = Map(json.loads(response))
x.__class__ = MyClass

कहाँ पे

class Map(dict):
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self[k] = v
                    if isinstance(v, dict):
                        self[k] = Map(v)

        if kwargs:
            # for python 3 use kwargs.items()
            for k, v in kwargs.iteritems():
                self[k] = v
                if isinstance(v, dict):
                    self[k] = Map(v)

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

एक सामान्य, भविष्य प्रूफ समाधान के लिए।


-5

jsonमॉड्यूल का उपयोग करें ( पायथन 2.6 में नया ) या वह simplejsonमॉड्यूल जो लगभग हमेशा स्थापित होता है।


2
अरे, जवाब देने के लिए धन्यवाद। क्या आप JSON को डिकोड करने और फिर उस डेटा तक पहुंचने का एक उदाहरण पोस्ट कर सकते हैं?
साईं कृष्णा

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

1
@Zach: मेरे द्वारा लिंक किए गए डॉक्स के ठीक ऊपर उदाहरण हैं।
क्रिस मॉर्गन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.