Skip to content

Commit c284801

Browse files
committed
push all
1 parent 6ad1014 commit c284801

26 files changed

+774
-219
lines changed

JsonClassGeneratorLib/CodeWriters/PythonCodeWriter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public void WriteClassMembers(IJsonClassGeneratorConfig config, StringBuilder sw
9090
string classPropertyName = field.MemberName;
9191
string propertyAttribute = field.JsonMemberName;
9292
string internalPropertyAttribute = "_" + propertyAttribute;
93-
sw.AppendFormat(" {0}: {1}{2}", propertyAttribute, field.Type.GetTypeName(), Environment.NewLine);
93+
sw.AppendFormat(" {0}: {1}{2}", propertyAttribute, field.Type.GetTypeName(), Environment.NewLine);
9494

9595
string mappingFragment = string.Format("obj.get(\"{0}\")", propertyAttribute);
9696
string mappingFragment2 = string.Format(GetTypeFunctionName(field.Type, config), mappingFragment);
@@ -105,8 +105,8 @@ public void WriteClassMembers(IJsonClassGeneratorConfig config, StringBuilder sw
105105

106106
// Write Dictionnary Mapping Functions
107107
sw.AppendLine();
108-
sw.AppendLine(" @staticmethod");
109-
sw.AppendLine(string.Format(" def from_dict(obj: Any) -> '{0}':", type.AssignedName));
108+
sw.AppendLine(" @staticmethod");
109+
sw.AppendLine(string.Format(" def from_dict(obj: Any) -> '{0}':", type.AssignedName));
110110
sw.Append(mappingFunction.ToString());
111111
sw.AppendLine(string.Format(" return {0}({1})", type.AssignedName, fields.ToString()));
112112
}

JsonClassGeneratorLib/JsonClassGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ private IList<JsonType> HandleDuplicateClasses(IList<JsonType> types)
273273
// TODO: This is currently O(n*n) because it iterates through List<T> on every loop iteration. This can be optimized.
274274

275275
List<JsonType> typesWithNoDuplicates = new List<JsonType>();
276-
276+
types = types.OrderBy(p => p.AssignedName).ToList();
277277
foreach (JsonType type in types)
278278
{
279279
if (!typesWithNoDuplicates.Exists(p => p.OriginalName == type.OriginalName))
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from typing import List
2+
from typing import Any
3+
from dataclasses import dataclass
4+
import json
5+
@dataclass
6+
class Awesomeobject:
7+
SomeProps1: int
8+
SomeProps2: str
9+
10+
@staticmethod
11+
def from_dict(obj: Any) -> 'Awesomeobject':
12+
_SomeProps1 = int(obj.get("SomeProps1"))
13+
_SomeProps2 = str(obj.get("SomeProps2"))
14+
return Awesomeobject(_SomeProps1, _SomeProps2)
15+
16+
@dataclass
17+
class User:
18+
id: str
19+
name: str
20+
created_at: str
21+
updated_at: str
22+
email: str
23+
testanadditionalfield: str
24+
25+
@staticmethod
26+
def from_dict(obj: Any) -> 'User':
27+
_id = str(obj.get("id"))
28+
_name = str(obj.get("name"))
29+
_created_at = str(obj.get("created_at"))
30+
_updated_at = str(obj.get("updated_at"))
31+
_email = str(obj.get("email"))
32+
_testanadditionalfield = str(obj.get("testanadditionalfield"))
33+
return User(_id, _name, _created_at, _updated_at, _email, _testanadditionalfield)
34+
35+
@dataclass
36+
class Class1:
37+
id: int
38+
user_id: str
39+
awesomeobject: Awesomeobject
40+
created_at: str
41+
updated_at: str
42+
users: List[User]
43+
44+
@staticmethod
45+
def from_dict(obj: Any) -> 'Class1':
46+
_id = int(obj.get("id"))
47+
_user_id = str(obj.get("user_id"))
48+
_awesomeobject = Awesomeobject.from_dict(obj.get("awesomeobject"))
49+
_created_at = str(obj.get("created_at"))
50+
_updated_at = str(obj.get("updated_at"))
51+
_users = [User.from_dict(y) for y in obj.get("users")]
52+
return Class1(_id, _user_id, _awesomeobject, _created_at, _updated_at, _users)
53+
54+
@dataclass
55+
class Class2:
56+
SomePropertyOfClass2: str
57+
58+
@staticmethod
59+
def from_dict(obj: Any) -> 'Class2':
60+
_SomePropertyOfClass2 = str(obj.get("SomePropertyOfClass2"))
61+
return Class2(_SomePropertyOfClass2)
62+
63+
@dataclass
64+
class Root:
65+
Class1: Class1
66+
Class2: Class2
67+
68+
@staticmethod
69+
def from_dict(obj: Any) -> 'Root':
70+
_Class1 = Class1.from_dict(obj.get("Class1"))
71+
_Class2 = Class2.from_dict(obj.get("Class2"))
72+
return Root(_Class1, _Class2)
73+
74+
# Example Usage
75+
# jsonstring = json.loads(myjsonstring)
76+
# root = Root.from_dict(jsonstring)
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<p>There are many ways you can convert a Json object to Python classes. This tools 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:&nbsp;</p>
2+
<h3><strong>1. Create a DataClass for each Json Root Node</strong></h3>
3+
<p>Let's take the below JSON string as example and work with it during the steps:</p>
4+
<pre><code>{
5+
""Test"":<br /> {
6+
""id"":4,
7+
""userid"":""user_id_value"",
8+
""users"":[
9+
{
10+
""id"":""2"",
11+
""name"":""Test""
12+
},
13+
{
14+
""id"":""6"",
15+
""name"":""Test Child 1""
16+
}
17+
]
18+
}
19+
}</code></pre>
20+
<p>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"".</p>
21+
<p>We can write our Python class along with Its properties as such:/p&gt;</p>
22+
<pre><code>
23+
from dataclasses import dataclass
24+
from typing import List
25+
26+
@@dataclass
27+
class User:
28+
id: str
29+
name: str
30+
31+
@@dataclass
32+
class Test:
33+
id: int
34+
userid: str
35+
users: List[User]
36+
</code></pre>
37+
<p>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</p>
38+
<p>x = json.loads(my_json_string)</p>
39+
<p>and accessing the dictionary values by using x[""my_json_key""]</p>
40+
<p>However, translating these dictionary items to type safe Python properties require a few additional steps that we need to do.</p>
41+
<h3><strong>2. Map each Json Attribute to a Type Safe Python Property</strong></h3>
42+
<p>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:</p>
43+
<pre><code>
44+
from dataclasses import dataclass
45+
from typing import Any, List
46+
47+
@@dataclass
48+
class User:
49+
id: str
50+
name: str
51+
52+
@@staticmethod
53+
def from_dict(obj: Any) -&gt; 'User':
54+
_id = int(obj.get(""id""))
55+
_name = str(obj.get(""name""))
56+
return User(_id, _name)
57+
58+
@@dataclass
59+
class Test:
60+
id: int
61+
userid: str
62+
users: List[User]
63+
64+
@@staticmethod
65+
def from_dict(obj: Any) -&gt; 'Test':
66+
_id = int(obj.get(""id""))
67+
_userid = str(obj.get(""userid""))
68+
_users = [User.from_dict(y) for y in obj.get(""users"")]
69+
return Test(_id, _userid, _users)
70+
</code></pre>
71+
<p>We create a static method called ""from_dic"" and inside this method we created local properties (""_id, _name"") and for each property we are calling our dictionary supplying the keys found in our Json string.</p>
72+
<p>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:&nbsp;</p>
73+
<p><code> _users = [User.from_dict(y) for y in obj.get(""users"")]</code>&nbsp;</p>
74+
<p>Finally, we are returning a mapped object as seen in the last lines of the ""fom_dict"" method:</p>
75+
<p><code> return Test(_id, _userid, _users)</code></p>
76+
<h3><strong>3. Wrap your Python Object with a Root Class</strong></h3>
77+
<p>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.&nbsp;</p>
78+
<p>We can achieve this by adding the below code to your Python Script:</p>
79+
<pre><code>@@dataclass
80+
class Root:
81+
Test: Test
82+
83+
@@staticmethod
84+
def from_dict(obj: Any) -&gt; 'Root':
85+
_Test = Test.from_dict(obj.get(""Test""))
86+
return Root(_Test)</code></pre>
87+
<h3><strong>4. Call the Mapping Function at the Root Class&nbsp;</strong></h3>
88+
<p>Finally, in order to use our mapping functions, we need to call the Root mapping function ""from_dict"" as such :&nbsp;</p>
89+
<pre><code># Load the json string to a variable
90+
output = json.load(open('data.json'))<br />
91+
# Call the mapping function
92+
result = Root.from_dict(output)<br />
93+
# Access your Python properties
94+
result.Test.userid
95+
<br /></code></pre>
96+
<h3><strong>5. Use the Online Tool Above to Generate Python Classes from Json Strings</strong></h3>
97+
<p>You 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 !</p>
98+
<p>The full Python script will look like this:</p>
99+
<pre><code>
100+
from dataclasses import dataclass
101+
from typing import Any, List
102+
import json
103+
104+
@@dataclass
105+
class User:
106+
id: str
107+
name: str
108+
109+
@@staticmethod
110+
def from_dict(obj: Any) -&gt; 'User':
111+
_id = int(obj.get(""id""))
112+
_name = str(obj.get(""name""))
113+
return User(_id, _name)
114+
115+
@@dataclass
116+
class Test:
117+
id: int
118+
userid: str
119+
users: List[User]
120+
121+
@@staticmethod
122+
def from_dict(obj: Any) -&gt; 'Test':
123+
_id = int(obj.get(""id""))
124+
_userid = str(obj.get(""userid""))
125+
_users = [User.from_dict(y) for y in obj.get(""users"")]
126+
return Test(_id, _userid, _users)
127+
128+
@@dataclass
129+
class Root:
130+
Test: Test
131+
132+
@@staticmethod
133+
def from_dict(obj: Any) -&gt; 'Root':
134+
_Test = Test.from_dict(obj.get(""Test""))
135+
return Root(_Test)
136+
137+
138+
# Load the json string to a variable
139+
output = json.load(open('data.json'))
140+
# Call the mapping function
141+
result = Root.from_dict(output)
142+
# Access your Python properties
143+
result.Test.userid
144+
</code></pre>

TESTS-JSON-TO-PYTHON/data.json

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
1-
{
2-
"Class1":{
3-
"id":4,
4-
"user_id":"user_id_value",
5-
"awesomeobject": {"SomeProps1" : 1, "SomeProps2" : "test"},
6-
"created_at":"2015-06-02 23:33:90",
7-
"updated_at":"2015-06-02 23:33:90",
8-
"users":[
9-
{
10-
"id":"6",
11-
"name":"Test Child 1",
12-
"created_at":"2015-06-02 23:33:90",
13-
"updated_at":"2015-06-02 23:33:90",
14-
"email":"test@gmail.com"
15-
},
16-
{
17-
"id":"6",
18-
"name":"Test Child 1",
19-
"created_at":"2015-06-02 23:33:90",
20-
"updated_at":"2015-06-02 23:33:90",
21-
"email":"test@gmail.com",
22-
"testanadditionalfield":"tet"
23-
}
24-
]
25-
},
26-
27-
"Class2" : {
28-
"SomePropertyOfClass2" : "SomeValueOfClass2"
29-
}
1+
{
2+
"Test":{
3+
"id":4,
4+
"userid":"user_id_value",
5+
"object": {"prop1" : 1, "prop2" : "test"},
6+
"created_at":"2012-06-02 23:33:90",
7+
"updated_at":"2013-06-02 23:33:90",
8+
"users":[
9+
{
10+
"id":"2",
11+
"name":"Test"
12+
},
13+
{
14+
"id":"6",
15+
"name":"Test Child 1"
16+
}
17+
]
18+
},
19+
20+
"Test2" : {
21+
"Prop2" : "SomeVal2"
22+
}
3023
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from dataclasses import dataclass
2+
from typing import Any, List
3+
import json
4+
5+
@dataclass
6+
class User:
7+
id: str
8+
name: str
9+
10+
@staticmethod
11+
def from_dict(obj: Any) -> 'User':
12+
_id = int(obj.get("id"))
13+
_name = str(obj.get("name"))
14+
return User(_id, _name)
15+
16+
@dataclass
17+
class Test:
18+
id: int
19+
userid: str
20+
users: List[User]
21+
22+
@staticmethod
23+
def from_dict(obj: Any) -> 'Test':
24+
_id = int(obj.get("id"))
25+
_userid = str(obj.get("userid"))
26+
_users = [User.from_dict(y) for y in obj.get("users")]
27+
return Test(_id, _userid, _users)
28+
29+
@dataclass
30+
class Root:
31+
Test: Test
32+
33+
@staticmethod
34+
def from_dict(obj: Any) -> 'Root':
35+
_Test = Test.from_dict(obj.get("Test"))
36+
return Root(_Test)
37+
38+
39+
# Load the json string to a variable
40+
output = json.load(open('data.json'))
41+
# Call the mapping function
42+
result = Root.from_dict(output)
43+
# Access your Python properties
44+
result.Test.userid

0 commit comments

Comments
 (0)