কীভাবে জেএসএন ডেটাটিকে পাইথন অবজেক্টে রূপান্তর করা যায়


281

আমি JSON ডেটাটিকে পাইথন অবজেক্টে রূপান্তর করতে পাইথনটি ব্যবহার করতে চাই।

আমি ফেসবুক এপিআই থেকে জেএসএন ডেটা অবজেক্টগুলি পেয়েছি, যা আমি আমার ডাটাবেসে সংরক্ষণ করতে চাই।

জাজানো (পাইথন) এ আমার বর্তমান দর্শন ( request.POSTজেএসওএন রয়েছে):

response = request.POST
user = FbApiUser(user_id = response['id'])
user.name = response['name']
user.username = response['username']
user.save()
  • এটি দুর্দান্ত কাজ করে তবে আমি কীভাবে জটিল JSON ডেটা অবজেক্ট পরিচালনা করব?

  • আমি যদি কোনওভাবেই সহজেই ব্যবহারের জন্য এই JSON অবজেক্টটিকে পাইথন অবজেক্টে রূপান্তর করতে পারি তবে এটি আরও ভাল হত না?


সাধারণত জেএসএন ভ্যানিলা তালিকায় বা ডিক্টে রূপান্তরিত হয়। তুমি কি এটাই চাও? অথবা আপনি জাস্টসকে সরাসরি একটি পছন্দসই ধরণের রূপান্তর করতে চান?
শাকাকাই

আমি এটিকে একটি অবজেক্টে রূপান্তর করতে চাই, "" ব্যবহার করে আমি অ্যাক্সেস করতে পারি এমন কিছু। । উপরের উদাহরণ থেকে পছন্দ করুন -> reponse.name, प्रतिक्रिया.education.id ইত্যাদি ....
সাঁই কৃষ্ণ

44
dictS ব্যবহার করা অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ের একটি দুর্বল-সস উপায়। অভিধানগুলি আপনার কোডের পাঠকদের কাছে প্রত্যাশাগুলি জানানোর খুব দরিদ্র উপায়। অভিধান ব্যবহার করে, আপনি কীভাবে পরিষ্কার এবং পুনরায় ব্যবহার করতে পারেন যে কিছু অভিধান কী-মান জোড়া প্রয়োজন, অন্যগুলি না করে? একটি প্রদত্ত মান গ্রহণযোগ্য পরিসরে বা সেটে রয়েছে তা নিশ্চিত করার বিষয়ে কী? আপনি যে ধরণের অবজেক্টের সাথে কাজ করছেন তার সুনির্দিষ্ট ফাংশন সম্পর্কে (ওরফে পদ্ধতিগুলি) কী? অভিধানগুলি হস্তান্তরিত এবং বহুমুখী, তবে অনেকগুলি ডেভস কাজ করে যেমন তারা ভুলে গিয়েছিল যে কোনও কারণে পাইথন একটি উদ্দেশ্য ভিত্তিক ভাষা।
স্টিউ

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
এর ফলে একটি মান ত্রুটি হতে পারে, ভ্যালু এরির: প্রকারের নাম এবং ক্ষেত্রের নামগুলি একটি সংখ্যা দিয়ে শুরু করতে পারে না: '123'
পিভিডিএল

3
পাইথনের নবাগত হিসাবে, আমি আগ্রহী যদি সুরক্ষার সমস্যা হয় তখনও যদি এটি কোনও সেভ জিনিস হয়।
বেনজিস্ট

8
পার্সিং করার সময় এটি প্রতিটিবার একটি JSON অবজেক্টের মুখোমুখি একটি নতুন আলাদা শ্রেণি তৈরি করে , তাই না?
fikr4n

2
মজাদার. আমি ভেবেছিলাম একই ক্রমে ভরসা করা d.keys()এবং d.values()পুনরাবৃত্তি করা গ্যারান্টিযুক্ত নয় তবে আমি ভুল ছিল। ডক্স বলে, "কি, মান এবং আইটেম মতামত অভিধান কোন হস্তক্ষেপ সংশোধনসহ উপর iterated হয়, আইটেম অর্ডার সরাসরি মিলা হবে।"। এ জাতীয় ছোট, স্থানীয় কোড ব্লকগুলির জন্য জানা ভাল। আমি যেমন একটি মন্তব্য যোগ করব যদিও স্পষ্টভাবে এই জাতীয় নির্ভরতার কোড রক্ষণাবেক্ষণকারীদের সতর্ক করতে।
সিএফআই

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 অবজেক্টগুলিকে অভিধানে রূপান্তর করব এবং অভিধান থেকে এই ডেটা কীভাবে অ্যাক্সেস করব?
সাঁই কৃষ্ণ

আশ্চর্যজনক, এটি প্রায় পরিষ্কার, আরও একটি ছোট জিনিস জানতে চেয়েছিলেন যে যদি এই অবজেক্ট থাকে -> education 'শিক্ষা': {'name1': 456, 'name2': 567}}, আমি কীভাবে এই ডেটা অ্যাক্সেস করব?
সায় কৃষ্ণ

এটি কেবল শীর্ষস্থানীয় লেভেলডেটা হবে ['শিক্ষা'] ['নাম 1'] ==> 456? বোঝা যায়?
শাকাকাই

1
@ বেন: আমি মনে করি আপনার মন্তব্য অনুপযুক্ত। এখানে সমস্ত উত্তরগুলির মধ্যে বর্তমানে ক্লাসটি সঠিকভাবে পাওয়া একমাত্র। যার অর্থ: এটি একটি পাসের অপারেশন এবং ফলাফলটি সঠিক ধরণের ব্যবহার করে। আচার নিজেই JSON (বাইনারি বনাম পাঠ্য rep) এর চেয়ে আলাদা অ্যাপ্লিকেশনের জন্য এবং jsonpickle একটি নন-স্ট্যান্ডার্ড লাইব। আমি আগ্রহী যে আপনি কীভাবে এই সমস্যার সমাধান করছেন তা দেখতে আগ্রহী হবেন যে std json lib বস্তু হুককে উপরের পার্স গাছ সরবরাহ করে না
সিএফআই

আমাকে এই বিষয়ে @ বেনের সাথে একমত হতে হবে। এটি একটি সত্যই খারাপ সমাধান। মোটেও স্কেলেবল নয়। আপনার ক্ষেত্রের নামগুলি স্ট্রিং হিসাবে এবং ক্ষেত্র হিসাবে বজায় রাখতে হবে। আপনি যদি আপনার ক্ষেত্রগুলিকে রিফেক্টর করতে চান তবে ডিকোডিং ব্যর্থ হবে (অবশ্যই ইতিমধ্যে সিরিয়ালযুক্ত ডেটা আর কোনওভাবে প্রাসঙ্গিক হবে না)। একই ধারণাটি ইতিমধ্যে জসনপিকলের
লোকারাড d ই

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সজ্জাকারীর সাথে একই বৈশিষ্ট্য সরবরাহ করে । মার্শমেলো.ড্রেডহেডসকস.ওআইও
এএন /

3
আরগপার্সের উপর নির্ভরতা এড়াতে: আরগপার্স আমদানিটি এর সাথে প্রতিস্থাপন করুন from types import SimpleNamespaceএবং ব্যবহার করুন:x = json.loads(data, object_hook=lambda d: SimpleNamespace(**d))
ম্যাক্সচলেপজিগ

8
এটি সবচেয়ে মার্জিত সমাধান, শীর্ষে থাকা উচিত।
স্কেলাউইলিয়াম

4
পাইথন ৩.x এর অধীনে চলার সময় @ ম্যাক্সচেলেপজিগের সমাধান ব্যবহার করতে সম্পাদিত ( types.SimpleNamespaceদুর্ভাগ্যক্রমে ২.7-তে বিদ্যমান নেই)।
ড্যান লেন্সকি

1
কেন print_function?
চবি

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
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। অন্যান্য সকলের চেয়ে আমার পক্ষে বিজ্ঞাপনটি সবচেয়ে সহজ কাজ করেছে।
ইজিক

আমি * আরগস, ** কাওয়ার্গ ব্যবহার করিনি, তবে সমাধানটি কার্যকর হয়েছে।
মালকাভিয়ানো

1
ব্যবহারকারী (** জে) বলছেন এটির নাম এবং ব্যবহারকারীর নাম প্যারামিটারগুলি অনুপস্থিত রয়েছে, এছাড়াও ডিকটি কীভাবে আরম্ভ হবে?
অ্যারন স্টেইনব্যাক

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

জটিল বস্তুর জন্য, আপনি জেএসএন পিকেল ব্যবহার করতে পারেন

জেএসএন-তে যেকোন স্বেচ্ছাচারিত বস্তু গ্রাফকে সিরিয়াল করার জন্য পাইথন লাইব্রেরি। এটি প্রায় কোনও পাইথন অবজেক্ট নিতে পারে এবং বস্তুকে জেএসএনে রূপান্তর করতে পারে। অতিরিক্তভাবে, এটি পাইথনে আবার বস্তুর পুনর্গঠন করতে পারে।


6
আমি মনে করি জাসনস্ট্রাক্ট আরও ভাল। 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
জসনস্ট্রাক্টের সমস্যাগুলি হ'ল এটি রক্ষণাবেক্ষণের মতো দেখা যায় না (বাস্তবে, এটি পরিত্যক্ত দেখাচ্ছে) এবং এটি বস্তুর তালিকায় যেমন রূপান্তর করতে ব্যর্থ হয় '[{"name":"object1"},{"name":"object2"}]'। jsonpickle এটি খুব ভালভাবে পরিচালনা করে না।
এলএস

1
আমার উত্তর নেই কেন এই উত্তরটি বেশি ভোট পাচ্ছে না। বেশিরভাগ অন্যান্য সমাধান বেশ বাইরে রয়েছে। কেউ জেএসএন ডি / সিরিয়ালাইজেশনের জন্য একটি দুর্দান্ত গ্রন্থাগার তৈরি করেছেন - কেন এটি ব্যবহার করবেন না? তদতিরিক্ত, তালিকাগুলি ভাল কাজ করছে বলে মনে হচ্ছে - এটি আপনার @ এলএস নিয়ে কী ছিল?
গেয়ারাড

1
@ গুয়ারাড, সমস্যাটি হ'ল: x = jsonpickle.decode ('[[{"নাম": "অবজেক্ট 1"}, {"নাম": "অবজেক্ট 2"}]' ') অভিধানের একটি তালিকা দেয় ([{' নাম ':' অবজেক্ট 1 '}, name' নাম ':' অবজেক্ট 2 '}]), বৈশিষ্ট্যযুক্ত বস্তুর তালিকা নয় (x [0]। নাম ==' অবজেক্ট 1 '), যা মূল প্রশ্নের প্রয়োজন। এটি পেতে, আমি এডিজিকের প্রস্তাবিত অবজেক্ট_হুক / নেমস্পেস পদ্ধতির ব্যবহারটি শেষ করেছিলাম, তবে উবারশ্মেকেলের দ্রুত / নোংরা পদ্ধতিটিও বেশ ভাল দেখাচ্ছে। আমি মনে করি আমি jsonpickle এর set_encoder_options () (undocumented!) দিয়ে অবজেক্ট_হুকটি ব্যবহার করতে পারি, তবে এটি বেসিক জসন মডিউলটির চেয়ে বেশি কোড নিতে পারে। আমি ভুল প্রমাণিত হতে চাই!
এল এস

@ এলএসের যদি আপনার ইনপুটটির উপর নিয়ন্ত্রণ না থাকে তবে ওপি যা বলেছিল তা সত্যই নয়, জেসনপিকল আদর্শ নয় কারণ এটি প্রতিটি স্তরে প্রকৃত ধরণের প্রত্যাশা করে (এবং অনুপস্থিত থাকলে মূল ধরণগুলি গ্রহণ করবে)। উভয় সমাধান "চতুর"।
লোকারাড

12

যদি আপনি পাইথন ৩.৫+ ব্যবহার করেন তবে আপনি 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)

আপনার বর্গ পাইথন ডিফল্ট ধরনের, স্ট্রিং, ইন্টিজার, তালিকা, datetimes ইত্যাদি নিয়ে গঠিত যদি এই উদাহরণগুলি কাজ করবে jsonsliberal এর সংক্ষিপ্ত রূপ কাস্টম ধরনের যদিও জন্য টাইপ নির্দেশ প্রয়োজন হবে।


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'
JOhn

@ জোহান: আপনার গিথুব
লভাসোয়া /

5

আমি যে কোনও 2 নামক একটি ছোট (ডি) সিরিয়ালাইজেশন কাঠামো লিখেছি যা দুটি পাইথনের ধরণের মধ্যে জটিল রূপান্তর করতে সহায়তা করে।

আপনার ক্ষেত্রে, আমি অনুমান করি যে আপনি একটি অভিধান থেকে (কোনও প্রাপ্ত json.loads) response.education ; response.nameএকটি নেস্টেড কাঠামো response.education.idইত্যাদির সাথে কোনও জটিল অবজেক্টে রূপান্তর করতে চান ... সুতরাং ঠিক এই কাঠামোর জন্য তৈরি করা হয়েছে। ডকুমেন্টেশন এখনও দুর্দান্ত নয়, তবে ব্যবহার করে any2any.simple.MappingToObjectআপনি খুব সহজেই এটি করতে সক্ষম হবেন। আপনার যদি সাহায্যের প্রয়োজন হয় তবে দয়া করে জিজ্ঞাসা করুন।


সেপপিক, যে কোনও 2 টি ইনস্টল করেছেন এবং পদ্ধতি কলগুলির উদ্দেশ্য অনুসারে বুঝতে সমস্যা হচ্ছেন having আপনি কি প্রতিটি কি জন্য একটি সম্পত্তি সঙ্গে পাইথন অবজেক্টে একটি অভিধান রূপান্তর একটি সাধারণ উদাহরণ দিতে পারেন?
সংস্জ

হাই @ সানসজো! আপনি যদি এটি পাইপি থেকে ইনস্টল করেন তবে সংস্করণটি পুরানো হয়ে গেছে, কয়েক সপ্তাহ আগে আমি একটি সম্পূর্ণ রিফ্যাক্টরিং করেছি। আপনার গিথুব সংস্করণটি ব্যবহার করা উচিত (আমার সঠিক প্রকাশ করা দরকার!)
সেপ্টপিক

আমি এটি পাইপাই থেকে ইনস্টল করেছি কারণ গিথুব এটি পাইপি থেকে ইনস্টল করতে বলেছিল। এছাড়াও, আপনি বলেছিলেন যে পাইপি মাসখানেক আগে পুরানো হয়ে পড়েছিল .. এটি কার্যকর হয়নি :( আমি একটি বাগ রিপোর্ট দায়ের করেছি! Github.com/sebpiq/any2any/issues/11
স্নিলান

5

লোভাসোয়া এর খুব ভাল উত্তর উন্নতি করছে।

যদি আপনি পাইথন 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 = ডেটাগ্লাস থেকে সত্য এবং আপনি যেতে ভাল to
জোসেফ কোরবেল

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

কোনও ফাইল থেকে লোড করতে @ ডিএসএস প্রতিক্রিয়াটিকে কিছুটা সংশোধন করা হচ্ছে:

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_ প্রথম_পথ" কোনও বৈধ পাইথন ক্ষেত্রের নাম নয়।


2

সমাধান অনুসন্ধান করার সময়, আমি এই ব্লগ পোস্টে হোঁচট খেয়েছি: https://blog.mosthege.net/2016/11/12/json-deserialization-of-nested-objects/

এটি পূর্ববর্তী উত্তরে বর্ণিত একই কৌশলটি ব্যবহার করে তবে সাজসজ্জার ব্যবহারের সাথে। আর একটি জিনিস যা আমি দরকারী বলে মনে করি তা হ'ল এটি deserialisation শেষে একটি টাইপ করা বস্তুটি ফেরত দেয়

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

আপনি যদি পাইথন ৩.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()

এটি জেভিএম ভাষা করার পদ্ধতিগুলির সাথেও বেশি মিল।
জাভাদবা

1

আমি এমন একটি সমাধান অনুসন্ধান করছিলাম যা কাজ করে recordclass.RecordClass, নেস্টেড বস্তুগুলিকে সমর্থন করে এবং জসন সিরিয়ালাইজেশন এবং জসন ডিসরিয়ালিশন উভয়ের পক্ষে কাজ করে।

ডিএসের উত্তরটি প্রসারিত করা, এবং বেনিএসআর্ট থেকে সমাধানটি প্রসারিত করার সময় আমি নিম্নলিখিতগুলি নিয়ে কাজ করেছি বলে মনে হচ্ছে:

কোড:

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

এখানে প্রদত্ত উত্তরগুলি সঠিক অবজেক্টের ধরণটি দেয় না, তাই আমি নীচে এই পদ্ধতিগুলি তৈরি করেছি। আপনি যদি প্রদত্ত জেএসওএন-তে উপস্থিত না থাকা শ্রেণিতে আরও ক্ষেত্র যুক্ত করার চেষ্টা করেন তবে সেগুলিও ব্যর্থ হয়:

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

আমার জ্ঞানটি নিয়ে আমি যে সর্বোত্তম প্রচার করতে পারি তা হ'ল এটি।
মনে রাখবেন যে এই কোডটি ট্রিট সেট ()ও করে।
এই পদ্ধতির জেনারিক কেবল শ্রেণির সম্প্রসারণ প্রয়োজন (দ্বিতীয় উদাহরণে)।
নোট করুন যে আমি এটি কেবল ফাইলগুলিতে করছি তবে আপনার স্বাদে আচরণটি পরিবর্তন করা সহজ।

তবে এটি একটি কোডেক।

আরও কিছুটা কাজ করে আপনি নিজের ক্লাসটি অন্য উপায়ে তৈরি করতে পারেন। আমি এটির উদাহরণস্বরূপ একটি ডিফল্ট কনস্ট্রাক্টর ধরে নিই, আমি ক্লাস ডিক আপডেট করি।

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)

সম্পাদন করা

আরও কিছু গবেষণার সাহায্যে আমি একটি মেটাক্লাস ব্যবহার করে সুপারক্লাস নিবন্ধকরণ পদ্ধতি কলের প্রয়োজন ছাড়াই সাধারণকরণের একটি উপায় পেয়েছি

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মডিউল ( পাইথন ২.6 এ নতুন ) বা simplejsonপ্রায় সবসময় ইনস্টল থাকা মডিউলটি ব্যবহার করুন ।


2
আরে, জবাব দেওয়ার জন্য আপনাকে ধন্যবাদ। আপনি কীভাবে JSON ডিকোড করবেন এবং তারপরে সেই ডেটা অ্যাক্সেস করবেন তার উদাহরণ পোস্ট করতে পারেন?
সায় কৃষ্ণ

আরে, এখন আপনি একটি পয়েন্ট পেয়েছেন তবে একরকম, আমি না জেনে কাজ করা পছন্দ করি এবং তারপরে এটিকে বিপরীত ইঞ্জিনিয়ারিং: ডি
সায় কৃষ্ণ

1
@ জাচ: আমি যে ডক্সের সাথে লিঙ্ক করেছি তার শীর্ষে উদাহরণ রয়েছে।
ক্রিস মরগান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.