كيفية تحويل JSON إلى كائن Python
بيثون json
تحتوي المكتبة على العديد من الأدوات المساعدة لترميز البيانات وفك تشفيرها بتنسيق JSON. على وجه الخصوص ، فإن json.load()
طريقة فك شفرة JSON قراءة كملف ، و json.loads()
فك شفرة JSON قراءة كسلسلة. بشكل عام ، عند فك تشفير ملفات JSON ، يتم تحويل البيانات إلى قواميس Python ، ولكن من الممكن تحويلها إلى كائن مخصص باستخدام المعلمة object_hook
.
على سبيل المثال ، افترض أن لديك كائن JSON التالي:
json_obj = """{
"name" : "Felipe",
"email" : "[email protected]",
"age" : 29
}"""
والفئة التالية :
class User():
name : str
email : str
age : int
def __init__(self, input):
self.name = input.get("name")
self.email = input.get("email")
self.age = input.get("age")
إذا اتصلنا json.loads()
مع User
كما object_hook
المعلمة User.__init__()
سيتم استدعاء الطريقة مع JSON المطابق dict
كمدخل.
import json
user = json.loads(json_obj, object_hook = User)
print(f"User {user.name}, age {user.age}, email {user.email}")
User Felipe, age 29, email [email protected]
ولكن ماذا لو كان لديك JSON مدمج؟
json.loads()
يدعو في الواقع object_hook
تعمل في كل مرة تقرأ فيها كائن JSON مكتمل التكوين من السلسلة. ضع في اعتبارك JSON التالي ، المُعاد من ملف واجهة برمجة تطبيقات مولد المستخدم العشوائي
json_obj = """{
"gender": "male",
"name": {
"title": "Mr",
"first": "Ian",
"last": "Walters"
},
"location": {
"street": {
"number": 3161,
"name": "Saddle Dr"
},
"city": "Bendigo",
"state": "Western Australia",
"country": "Australia",
"postcode": 4285,
"coordinates": {
"latitude": "-84.7903",
"longitude": "-29.1020"
},
"timezone": {
"offset": "+9:00",
"description": "Tokyo, Seoul, Osaka, Sapporo, Yakutsk"
}
},
"email": "[email protected]",
"login": {
"uuid": "6ee5b2e8-01c3-4314-8f7f-80059f5dd9ec",
"username": "lazyzebra585",
"password": "walter",
"salt": "afXmogsa",
"md5": "a40e87023b57a4a60c7cb398584cbac3",
"sha1": "74caf43400be38cce60a8da2e6d1c367246505c2",
"sha256": "1becdf34bcc6704726c7e9b38821a5792f9dd0689d30789fb5e099a6e51e860a"
},
"dob": {
"date": "1947-06-06T02:45:41.895Z",
"age": 75
},
"registered": {
"date": "2003-03-25T00:15:32.791Z",
"age": 19
},
"phone": "06-9388-6976",
"cell": "0469-101-424",
"id": {
"name": "TFN",
"value": "561493929"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/32.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/32.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/32.jpg"
},
"nat": "AU"
}"""
دعنا نطبع JSON الذي تم فك ترميزه في كل خطوة لنرى ما سيحدث:
json.loads(json_obj, object_hook = print)
{'title': 'Mr', 'first': 'Ian', 'last': 'Walters'}
{'number': 3161, 'name': 'Saddle Dr'}
{'latitude': '-84.7903', 'longitude': '-29.1020'}
{'offset': '+9:00', 'description': 'Tokyo, Seoul, Osaka, Sapporo, Yakutsk'}
{'street': None, 'city': 'Bendigo', 'state': 'Western Australia', 'country': 'Australia', 'postcode': 4285, 'coordinates': None, 'timezone': None}
{'uuid': '6ee5b2e8-01c3-4314-8f7f-80059f5dd9ec', 'username': 'lazyzebra585', 'password': 'walter', 'salt': 'afXmogsa', 'md5': 'a40e87023b57a4a60c7cb398584cbac3', 'sha1': '74caf43400be38cce60a8da2e6d1c367246505c2', 'sha256': '1becdf34bcc6704726c7e9b38821a5792f9dd0689d30789fb5e099a6e51e860a'}
{'date': '1947-06-06T02:45:41.895Z', 'age': 75}
{'date': '2003-03-25T00:15:32.791Z', 'age': 19}
{'name': 'TFN', 'value': '561493929'}
{'large': 'https://randomuser.me/api/portraits/men/32.jpg', 'medium': 'https://randomuser.me/api/portraits/med/men/32.jpg', 'thumbnail': 'https://randomuser.me/api/portraits/thumb/men/32.jpg'}
{'gender': 'male', 'name': None, 'location': None, 'email': '[email protected]', 'login': None, 'dob': None, 'registered': None, 'phone': '06-9388-6976', 'cell': '0469-101-424', 'id': None, 'picture': None, 'nat': 'AU'}
So json.loads()
يدعو object_hook
تعمل في كل مرة تقرأ فيها JSON مكتمل التكوين ، أي في كل مرة تغلق فيها زوجًا من قوسين {}
. بعد ذلك ، يقوم بإنشاء كائن JSON بالكامل باستخدام نتيجة الامتداد object_hook
وظيفة - لاحظ None
(قيمة الإرجاع print
) في آخر سطر مطبوع.
سنعرض حلين لحل هذه المشكلة. الأول هو تعديل User.__init__()
أن تكون أكثر مرونة فيما يتعلق بالمدخلات. سنفعل هذا باستخدام __dict__
يصف. كل كائن بايثون له الامتداد __dict__
السمة التي تحمل اسم كل سمة وقيمتها. لدينا تعديل __init__()
ستعمل الطريقة على تحديث هذا القاموس:
class User():
def __init__(self, input):
self.__dict__.update(input)
user = json.loads(json_obj, object_hook = User)
print(f"User {user.name.first} {user.name.last}, age {user.dob.age}, email {user.email}")
تحقق من دليلنا العملي العملي لتعلم Git ، مع أفضل الممارسات ، والمعايير المقبولة في الصناعة ، وورقة الغش المضمنة. توقف عن أوامر Googling Git وفي الواقع تعلم ذلك!
User Ian Walters, age 75, email [email protected]
حل آخر ممكن هو استخدام collections.namedtuple
صف دراسي:
from collections import namedtuple
def create_user(input):
User = namedtuple('User', input.keys())
return User(**input)
user = json.loads(json_obj, object_hook=create_user)
print(f"User {user.name.first} {user.name.last}, age {user.dob.age}, email {user.email}")
User Ian Walters, age 75, email [email protected]
أين namedtuple('User', input.keys())
ينشئ فئة فرعية تسمى tuple User
باستخدام مفاتيح الإدخال كأسماء سمات ، و User(**input)
يعين القيم المقابلة للسمات.