简体   繁体   中英

Deserialize JSON string to a class instance automatically in Python

Assume I have several classes:

class Assignee:
    gid: str
    name: str
    
class Task:
    gid: str
    name: str
    created_at: datetime
    assignee: Assignee

and I receive a JSON, that I want to translate into my Task class instance:

{
 "gid": "#1",
 "name": "my task",
 "created_at": "2022-11-02T10:25:49.806Z",
 "assignee": {
  "gid": "#a1",
  "name": "assignee name"
 }
}

I need to get the strong typed result, not a dict. Is it possible to convert from JSON string to a class instance automatically? In C# we can do it with JsonConvert.DeserializeObject<Task>(json_string) . In Python I found a jsonpickle library, but as far as I see, it cannot do it automatically. Am I missing anything?

In real life I have many more classes and JSON properties.

Not quite what you are asking, but the json module already produces suitable dicts. All you need to do is define how to instantiate your classes given a dict .

Part of this requires you to assume what type each key's value must be instantiated as.

class Assignee:
    @classmethod
    def from_dict(cls, d):
        return cls(d['gid'], d['name'])

class Task:
    @classmethod
    def from_dict(cls, d):
        return cls(d['gid'], d['name'], d['created_at'], Assignee.from_dict(d['assignee']))

t = Task.from_dict(json.load('{"gid": "#1", ...}'))

Use pydantic . It has type validation (and other cool features) and is very easy to use:

from pydantic import BaseModel
from datetime import datetime

class Assignee(BaseModel):
    gid: str
    name: str
    

class Task(BaseModel):
    gid: str
    name: str
    created_at: datetime
    assignee: Assignee


data = {
    "gid": "#1",
    "name": "my task",
    "created_at": "2022-11-02T10:25:49.806Z",
    "assignee": {
        "gid": "#a1",
        "name": "assignee name"
    }
}

Task(**data)
>>>Task(gid='#1', name='my task', created_at=datetime.datetime(2022, 11, 2, 10, 25, 49, 806000, tzinfo=datetime.timezone.utc), assignee=Assignee(gid='#a1', name='assignee name'))

Assuming the json properties match the property names exactly in the classes, you can use kwargs in the constructors to put the object together.

import json

class Assignee:
    def __init__(self, gid, name):
        self.gid = gid
        self.name = name

class Task:
    def __init__(self, gid, name, created_at, assignee):
        self.gid = gid
        self.name = name
        self.created_at = created_at
        self.assignee = Assignee(**assignee)

json_string = '{ "gid": "123", "name": "Bob", "created_at": "1/1/1990", "assignee": { "gid": "234", "name": "Alice" } }'

# Instantiate Task with kwargs loaded from json
my_task = Task(**json.loads(json_string))

print(my_task.assignee.name)
# prints 'Alice'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM