Πώς να μετατρέψετε το 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)
εκχωρεί τις αντίστοιχες τιμές για τα χαρακτηριστικά.