نحوه تبدیل JSON به آبجکت پایتون

نحوه تبدیل JSON به آبجکت پایتون

پایتون json کتابخانه ابزارهای بسیاری برای رمزگذاری و رمزگشایی داده ها در قالب JSON دارد. به طور خاص، json.load() متد یک JSON خوانده شده به عنوان فایل را رمزگشایی می کند و json.loads() یک JSON خوانده شده به عنوان یک رشته را رمزگشایی کنید. به طور کلی، هنگام رمزگشایی فایل‌های JSON، داده‌ها به دیکشنری پایتون تبدیل می‌شوند، اما امکان تبدیل آن به یک شی سفارشی با استفاده از پارامتر وجود دارد. 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 زیر را در نظر بگیرید Random User Generator API

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 را با بهترین روش ها، استانداردهای پذیرفته شده در صنعت و برگه تقلب شامل بررسی کنید. دستورات Google 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()) یک زیر کلاس تاپل به نام ایجاد می کند User با کلیدهای ورودی به عنوان نام ویژگی ها، و User(**input) مقادیر مربوطه را برای صفات اختصاص می دهد.

تمبر زمان:

بیشتر از Stackabuse