Skip to content

Commit 8cb8d9e

Browse files
committed
✨ Add read json methods and tests
- read json string, object or file - expose and test
1 parent cf995e9 commit 8cb8d9e

2 files changed

Lines changed: 99 additions & 42 deletions

File tree

src/electionguard/serializable.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from dataclasses import dataclass
22
from datetime import datetime
33
from os import path
4-
from typing import Any, cast, TypeVar, Generic
4+
from typing import Any, cast, Type, TypeVar, Generic
55

66
from jsons import (
77
dump,
@@ -169,6 +169,44 @@ def write_json_file(
169169
json_file.write(write_json(object_to_write, strip_privates))
170170

171171

172+
def read_json(data: Any, class_out: Type[T]) -> T:
173+
"""
174+
Deserialize json file to object
175+
:param data: Json file data
176+
:param class_out: Object type
177+
:return: Deserialized object
178+
"""
179+
set_deserializers()
180+
return cast(T, loads(data, class_out))
181+
182+
183+
def read_json_object(data: Any, class_out: Type[T]) -> T:
184+
"""
185+
Deserialize json file to object
186+
:param data: Json file data
187+
:param class_out: Object type
188+
:return: Deserialized object
189+
"""
190+
set_deserializers()
191+
return cast(T, load(data, class_out))
192+
193+
194+
def read_json_file(class_out: Type[T], file_name: str, file_path: str = "") -> T:
195+
"""
196+
Deserialize json file to object
197+
:param class_out: Object type
198+
:param file_name: File name
199+
:param file_path: File path
200+
:return: Deserialized object
201+
"""
202+
set_deserializers()
203+
json_file_path: str = path.join(file_path, file_name + JSON_FILE_EXTENSION)
204+
with open(json_file_path, READ) as json_file:
205+
data = json_file.read()
206+
target: T = read_json(data, class_out)
207+
return target
208+
209+
172210
def set_serializers() -> None:
173211
"""Set serializers for jsons to use to cast specific classes"""
174212

tests/test_serializable.py

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,93 @@
1+
from dataclasses import dataclass
12
from unittest import TestCase
3+
from typing import Any, List, Optional
24
from os import remove
35

46
from electionguard.serializable import (
57
set_deserializers,
68
set_serializers,
9+
read_json,
10+
read_json_file,
11+
read_json_object,
12+
write_json,
713
write_json_file,
814
write_json_object,
9-
write_json,
1015
)
1116

1217

18+
@dataclass
19+
class NestedModel:
20+
"""Nested model for testing"""
21+
22+
test: int
23+
from_json_file: Optional[Any] = None
24+
25+
26+
@dataclass
27+
class DataModel:
28+
"""Data model for testing"""
29+
30+
test: int
31+
nested: NestedModel
32+
array: List[NestedModel]
33+
from_json_file: Optional[Any] = None
34+
35+
36+
JSON_DATA: DataModel = DataModel(
37+
test=1, nested=NestedModel(test=1), array=[NestedModel(test=1)]
38+
)
39+
EXPECTED_JSON_STRING = '{"array": [{"test": 1}], "nested": {"test": 1}, "test": 1}'
40+
EXPECTED_JSON_OBJECT = {
41+
"test": 1,
42+
"nested": {"test": 1},
43+
"array": [{"test": 1}],
44+
}
45+
46+
1347
class TestSerializable(TestCase):
14-
def test_write_json(self) -> None:
15-
# Arrange
16-
json_data = {
17-
"from_json_file": {},
18-
"test": 1,
19-
"nested": {"from_json_file": {}, "test": 1},
20-
"array": [{"from_json_file": {}, "test": 1}],
21-
}
22-
expected_json_string = (
23-
'{"test": 1, "nested": {"test": 1}, "array": [{"test": 1}]}'
24-
)
48+
def test_read_and_write_json(self) -> None:
49+
# Act
50+
json_string = write_json(JSON_DATA)
51+
52+
# Assert
53+
self.assertEqual(json_string, EXPECTED_JSON_STRING)
2554

2655
# Act
27-
json_string = write_json(json_data)
56+
read_json_data = read_json(json_string, DataModel)
2857

2958
# Assert
30-
self.assertEqual(json_string, expected_json_string)
59+
self.assertEqual(read_json_data, JSON_DATA)
3160

32-
def test_write_json_object(self) -> None:
33-
# Arrange
34-
json_data = {
35-
"from_json_file": {},
36-
"test": 1,
37-
"nested": {"from_json_file": {}, "test": 1},
38-
"array": [{"from_json_file": {}, "test": 1}],
39-
}
40-
expected_json_object = {
41-
"test": 1,
42-
"nested": {"test": 1},
43-
"array": [{"test": 1}],
44-
}
61+
def test_read_and_write_json_object(self) -> None:
62+
# Act
63+
json_object = write_json_object(JSON_DATA)
64+
65+
# Assert
66+
self.assertEqual(json_object, EXPECTED_JSON_OBJECT)
4567

4668
# Act
47-
json_object = write_json_object(json_data)
69+
read_json_data = read_json_object(json_object, DataModel)
4870

4971
# Assert
50-
self.assertEqual(json_object, expected_json_object)
72+
self.assertEqual(read_json_data, JSON_DATA)
5173

52-
def test_write_json_file(self) -> None:
74+
def test_read_and_write_json_file(self) -> None:
5375
# Arrange
54-
json_data = {
55-
"from_json_file": {},
56-
"test": 1,
57-
"nested": {"from_json_file": {}, "test": 1},
58-
"array": [{"from_json_file": {}, "test": 1}],
59-
}
60-
expected_json_data = (
61-
'{"test": 1, "nested": {"test": 1}, "array": [{"test": 1}]}'
62-
)
6376
file_name = "json_write_test"
6477
json_file = file_name + ".json"
6578

6679
# Act
67-
write_json_file(json_data, file_name)
80+
write_json_file(JSON_DATA, file_name)
6881

6982
# Assert
7083
with open(json_file) as reader:
71-
self.assertEqual(reader.read(), expected_json_data)
84+
self.assertEqual(reader.read(), EXPECTED_JSON_STRING)
85+
86+
# Act
87+
read_json_data = read_json_file(DataModel, file_name)
88+
89+
# Assert
90+
self.assertEqual(read_json_data, JSON_DATA)
7291

7392
# Cleanup
7493
remove(json_file)

0 commit comments

Comments
 (0)