There are many ways you can convert a Json object to Python classes. This tool uses one of these ways which uses static functions to map dictionary key values to type safe Python properties and classes. Here are the steps to convert Json to Python classes:
Let's take the below JSON string as example and work with it during the steps:
{
"Test":
{
"id":4,
"userid":"user_id_value",
"users":[
{
"id":"2",
"name":"Test"
},
{
"id":"6",
"name":"Test Child 1"
}
]
}
}
We can see that we need to create two classes : "Test" and "User" since "users" property is an array of object with "id" and "name".
We can write our Python classes along with their properties as such:
from dataclasses import dataclass
from typing import List
@dataclass
class User:
id: str
name: str
@dataclass
class Test:
id: int
userid: str
users: List[User]
In Python, It's really easy to load a json string to a dictionary and access the values by calling the dictionary keys. This can be done using
x = json.loads(my_json_string)
and accessing the dictionary values by using x["my_json_key"]
However, translating these dictionary items to type safe Python properties require a few additional steps that we need to do.
The next step that needs to be done is mapping each Json node and attributes to Python classes and properties. We can do so by creating a static method in our Python classes that's responsible for mapping our dictionary to our Python properties. The Python script will look like this:
from dataclasses import dataclass
from typing import Any, List
@dataclass
class User:
id: str
name: str
@staticmethod
def from_dict(obj: Any) -> 'User':
_id = int(obj.get("id"))
_name = str(obj.get("name"))
return User(_id, _name)
@dataclass
class Test:
id: int
userid: str
users: List[User]
@staticmethod
def from_dict(obj: Any) -> 'Test':
_id = int(obj.get("id"))
_userid = str(obj.get("userid"))
_users = [User.from_dict(y) for y in obj.get("users")]
return Test(_id, _userid, _users)
We create a static method called "from_dic" and inside this method we create local properties ("_id, _name") and for each property we are calling our dictionary supplying the keys found in our Json string -> obj.get("id") and then casting that object to Python types -> int(obj.get("id"))
Note that for Arrays and Lists, what we're doing is we are creating a list of Users and for each user, we are calling the "from_dict" method so that the User properties will be mapped as well. This can be seen in the line below:
_users = [User.from_dict(y) for y in obj.get("users")]
Finally, we are returning a mapped object as seen in the last lines of the "from_dict" method:
return Test(_id, _userid, _users)
You can optionally wrap your Python objects with a root class, and this is in case you have multiple classes in the root node of your Json string.
We can achieve this by adding the below code to our Python Script:
@dataclass
class Root:
Test: Test
@staticmethod
def from_dict(obj: Any) -> 'Root':
_Test = Test.from_dict(obj.get("Test"))
return Root(_Test)
Finally, in order to use our mapping functions, we need to call the Root mapping function "from_dict" as such :
# Load the json string to a variable
output = json.load(open('data.json'))
# Call the mapping function
result = Root.from_dict(output)
# Access your Python properties
result.Test.userid
You can always use the online tool above to achieve what we did in this example. Just paste your Json in the left text area, hit that convert button, and you will have your python classes with their mappings created automagically !
The full Python script will look like this:
from dataclasses import dataclass
from typing import Any, List
import json
@dataclass
class User:
id: str
name: str
@staticmethod
def from_dict(obj: Any) -> 'User':
_id = int(obj.get("id"))
_name = str(obj.get("name"))
return User(_id, _name)
@dataclass
class Test:
id: int
userid: str
users: List[User]
@staticmethod
def from_dict(obj: Any) -> 'Test':
_id = int(obj.get("id"))
_userid = str(obj.get("userid"))
_users = [User.from_dict(y) for y in obj.get("users")]
return Test(_id, _userid, _users)
@dataclass
class Root:
Test: Test
@staticmethod
def from_dict(obj: Any) -> 'Root':
_Test = Test.from_dict(obj.get("Test"))
return Root(_Test)
# Load the json string to a variable
output = json.load(open('data.json'))
# Call the mapping function
result = Root.from_dict(output)
# Access your Python properties
result.Test.userid
We can see our python mapping is working fine and we can access our properties like usual :