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.
CodePudding user response:
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'))
CodePudding user response:
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", ...}'))
CodePudding user response:
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'