Πώς να μετατρέψετε το JSON σε αντικείμενο Python

Πώς να μετατρέψετε το 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, που επιστράφηκε από το 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__ Χαρακτηριστικό. Κάθε αντικείμενο Python έχει ένα __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, με βέλτιστες πρακτικές, πρότυπα αποδεκτά από τον κλάδο και συμπεριλαμβανόμενο φύλλο εξαπάτησης. Σταματήστε τις εντολές του Git στο Google και πραγματικά μαθαίνουν το!

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