0

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.

4
  • No... not automatically. I mean I am sure someone has written a library that does it automatically but nothing that is built into python Commented Dec 17, 2022 at 19:34
  • Are those supposed to be dataclasses? Commented Dec 17, 2022 at 19:37
  • It's easy to learn the fields of a dataclass: Assignee.__dict__['__dataclass_fields__'].keys(). From there, you can probe what JSON .loads() gave you, and populate a newly created object. If you put the values into dict d, then Assignee(**d) produces what you want. Once you've put together an implementation you're happy with, please share it with us here. Commented Dec 17, 2022 at 19:44
  • It's not an automatic solution, I am looking for a library that can do the staff in one line, resolving data types. Commented Dec 17, 2022 at 20:07

3 Answers 3

3

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'))
Sign up to request clarification or add additional context in comments.

Comments

0

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", ...}'))

Comments

-1

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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.