Home > Enterprise >  Python Convert JSON Array to Corresponding List of Python Objects
Python Convert JSON Array to Corresponding List of Python Objects

Time:11-28

Couldn't find an already existing post that addressed how to do this: I have a JSON Array, like

[{'completed': 0, 'content': 'do smtng', 'deadline': 'Mon, 22 Nov 2021 00:00:00 GMT', 'id': 4, 'user_id': 7}, ...],

and would like to convert it to a Python List of Task objects (from the Task class I created).

How would I go about doing this?

CodePudding user response:

What you are looking to do is deserialize a json object to a class, I'm sure there are better answers than this one but here goes.

First Step: convert json array to python list

import json
# assuming it is a json object for now, you can loop through an do the same
json = {'completed': 0, 'content': 'do smtng', 'deadline': 'Mon, 22 Nov 2021 00:00:00 GMT', 'id': 4, 'user_id': 7}
job = json.loads(json)

Second Step: Converting our list to a class

There's not really a consensus here on how to do this. You can try libraries like attrs if your json is already formatted with the exact naming of your class, or you can do something manual like this:

import json
from dataclasses import dataclass


@dataclass
class Task:
    completed: int
    content: str
    deadline: str
    id: int
    user_id: int
    
    @classmethod
    def from_dict(cls, dict):
        return cls(completed=dict["completed"], content=dict["content"],
                   deadline=dict["deadline"], id=dict["id"],
                   user_id=dict["user_id"])

    @classmethod
    def from_json(cls, json_str: str):
        return cls.from_dict(json.loads(json_str))

You can perform input validation here too if you want but trying to keep it basic

CodePudding user response:

If you're ok with using external libraries, the simplest solution would be to use the builtin dataclasses module in Python 3.7 along with the dataclass-wizard library for (de)serialization purposes.

Here's a simple enough example using data classes to model your data in this case. Note that I'm using a new feature, patterned date and time, to de-serialize a custom pattern string to a datetime object. If you want to keep the data as a string, you can annotate it just like deadline: str instead. I was able to use the format codes from the docs on datetime.

import json
from dataclasses import dataclass

from dataclass_wizard import fromlist, asdict, DateTimePattern


@dataclass
class Task:
    completed: int
    content: str
    deadline: DateTimePattern['%a, %d %b %Y %H:%M:%S %Z']
    id: int
    user_id: int


list_of_dict = [
    {'completed': 0, 'content': 'do smtng', 'deadline': 'Mon, 22 Nov 2021 00:00:00 GMT', 'id': 4, 'user_id': 7},
]

# De-serialize JSON data into a list of Task instances
list_of_tasks = fromlist(Task, list_of_dict)
print(list_of_tasks)

# Serialize list of Task instances
json_string = json.dumps([asdict(task) for task in list_of_tasks])
print(json_string)

Output:

[Task(completed=0, content='do smtng', deadline=datetime.datetime(2021, 11, 22, 0, 0), id=4, user_id=7)]
[{"completed": 0, "content": "do smtng", "deadline": "2021-11-22T00:00:00", "id": 4, "userId": 7}]

To make things a bit simpler, you can opt to subclass from the JSONWizard Mixin class. The main benefit here is a bunch of added helper class methods, like list_to_json which will serialize a list of dataclass instances to JSON, which seems like it could be useful in this case. This example is similar to the one above; note the output is the same in any case.

from dataclasses import dataclass

from dataclass_wizard import JSONWizard, DateTimePattern


@dataclass
class Task(JSONWizard):
    completed: int
    content: str
    deadline: DateTimePattern['%a, %d %b %Y %H:%M:%S %Z']
    id: int
    user_id: int


list_of_dict = [
    {'completed': 0, 'content': 'do smtng', 'deadline': 'Mon, 22 Nov 2021 00:00:00 GMT', 'id': 4, 'user_id': 7},
]

# De-serialize JSON data into a list of Task instances
list_of_tasks = Task.from_list(list_of_dict)
print(list_of_tasks)

# Serialize list of Task instances
json_string = Task.list_to_json(list_of_tasks)
print(json_string)
  • Related