وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

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

0 7
زمان لازم برای مطالعه: 3 دقیقه


روش تبدیل 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"
        }"""

اجازه دهید print 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'}

بنابراین json.loads() تماس می گیرد object_hook تابع هر بار که یک JSON کاملاً تشکیل شده را می خواند، یعنی هر بار که یک جفت براکت را می بندد. {}. سپس، کل شی JSON را با استفاده از نتیجه ایجاد می کند object_hook تابع – توجه داشته باشید None (مقدار بازگشتی از print) در آخرین خط چاپ شده.

پیشنهاد می‌کنیم بخوانید:  راهنمای Heaps در پایتون

ما دو راه حل برای این موضوع نشان خواهیم داد. اولین مورد این است که ما را اصلاح کنیم 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}")
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) مقادیر مربوطه را برای صفات اختصاص می دهد.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-02 09:02:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید