objtyping Object converter with type definition
origin
Python is not strongly typed, and developers are not in the habit of typing data. While this is flexible, it is not convenient when dealing with complex business logic — the lack of type checking can make it difficult to find errors and code prompts when coding in the IDE. So this gadget was developed to solve it.
Basic usage
- First define the business class and define the type of each field through the class variable.
from typing import List
class Person:
name: str
age: int
class Company:
name: str
revenue: float
employees: List[Person]
Copy the code
Class variables are chosen because they are the most concise and intuitive. By contrast, if an instance variable is initialized in an __init__ method, there is no way to get type_hint; If you’re using an @property annotation or a getter, setter method, it’s a little bit more complicated. None of them are as simple and elegant as defining class variables directly. But there is a downside to using class variables: they are used as metadata here, so if you really need to define class-level shared variables, you can’t tell them apart. This problem can be solved later by developing custom annotations.
- The next step is to convert the dict-list nested data conforming to the class definition structure into an instance object of the class:
from objtyping import objtyping
company1 = objtyping.from_dict_list({
'name': 'Apple'.'revenue': 18.5.'employees': [{
'name': 'Tom'.'age': 20
}, {
'name': 'Jerry'.'age': 31
}]
}, Company)
Copy the code
Company1 is a complete Company object. You can use company1.name, company1.employees[0]. Name to access its properties.
- It is also possible to revert the business object back to the dict-list nested form
from objtyping import objtyping
dict_list = objtyping.to_dict_list(company1)
Copy the code
The dict_list object is a bunch of dict and list nested primitives
Usage scenarios
Initialize an object
Python doesn’t have as convenient a way to initialize an object as JS, but with this tool you can write:
from typing import List
from objtyping import objtyping
class Person:
name: str
age: int
class Company:
name: str
revenue: float
employees: List[Person]
def __str__(self) : # In fact, it is generally possible to use this simple
return "'{}' has {} employees: {}".format(self.name, len(self.employees), ' and '.join(map(lambda emp: emp.name, self.employees)))
if __name__ == '__main__':
company1 = objtyping.from_dict_list({
'name': 'Apple'.'revenue': 18.5.'employees': [{
'name': 'Tom'.'age': 20
}, {
'name': 'Jerry'.'age': 31
}]
}, Company)
print(company1)
Copy the code
Output result:
'Apple' has 2 employees: Tom and Jerry
Copy the code
Serialize/deserialize
Python’s common serialization requirements include JSON and YAML data formats, both of which have relatively complete processing libraries. But again, without emphasizing types, they deal with objects in the original dict-list format. This tool is perfect for further transformation.
json
The sample
import json
import sys
from typing import List
from objtyping import objtyping
class X:
x: int
y: str
class A:
q: str
a: str
b: int
c: List[X]
if __name__ == '__main__':
print("\r\n-----json-------")
json_obj = json.loads('{"q":9, "a":"Mark", "b":3, "c":[{"x":15, "y":"male"},{"x":9, "y":"female", "z":13}]}')
typed_obj = objtyping.from_dict_list(json_obj, A)
d_l_obj = objtyping.to_dict_list(typed_obj)
print(json.dumps(d_l_obj))
sys.exit()
Copy the code
The output
-----json-------
{"q": "9", "a": "Mark", "b": 3, "c": [{"x": 15, "y": "male"}, {"x": 9, "y": "female", "z": 13}]}
Copy the code
Note here: The property “q” was originally a number in the JSON structure, but since the class variable was defined as a string, it is typed as a string when converted to a business object — the objtyping tool attempts to cast between the underlying types as defined by the class.
yaml
The sample
import sys
from ruamel.yaml import YAML
from typing import List
from objtyping import objtyping
class X:
x: int
y: str
class A:
q: str
a: str
b: int
c: List[X]
if __name__ == '__main__':
print("\r\n-----yaml-------")
yaml = YAML()
yaml_obj = yaml.load(''' q: 9 a: Mark b: 3 c: - x: 15 y: male - x: 9 y: female z: 13 ''')
typed_obj = objtyping.from_dict_list(yaml_obj, A)
d_l_obj = objtyping.to_dict_list(typed_obj)
yaml.dump(d_l_obj, sys.stdout)
sys.exit()
Copy the code
The output
-----yaml-------
q: '9'
a: Mark
b: 3
c:
- x: 15
y: male
- x: 9
y: female
z: 13
Copy the code
Here the property “q” is also strongly typed.
Project Address:Github.com/songofhawk/…