我有一組python webservices,它們可以通過JSON POSTs獲取數據對象。在我的舊服務中,我有很多樣板可以對每個對象進行序列化和檢查JSON。隨着Python 3.5s新的打字和PEP 484我有這種感覺,可以大大減少。這值得麼?有沒有人有一個很好的解決方案?如何在Python 3.5中從JSONs初始化類時減少樣板文件?
其他信息
我的老樣板看起來像這樣爲每個對象:
class Data:
class Nested1:
def __init__(self, nested1_flat1):
self.nested1_flat1 = nested1_flat1
@classmethod
def from_jsond(cls, jsond):
# jsond : dict of strings, lists and dicts as usually receivied from reading JSON
kwargs = {}
for key, val in jsond.items():
# lots of code to deal with special objects , e.g.
if key=='date' : kwargs[key] = cleverly_build_datetime_from_js_format(val)
return cls.__init__(**kwargs)
def __init__(self, flat1, nested1):
self.flat1 = flat1
self.nested1 = nested1
@classmethod
def from_jsond(cls, jsond):
kwargs = {}
for key, val in jsond.items():
# lots of code to deal with nested and special objects, e.g.
if key=='nested1' : kwargs[key] = Nested1.from_jsond(val)
return cls.__init__(**kwargs)
我設法減少它歸結爲以下
@from_jsond
class Data:
@from_jsond
class Nested1:
@auto_assign
@beartype
def __init__(self, nested1_flat1: str):
pass
@auto_assign
@beartype
def __init__(self, flat1: str, nested1: Nested1)
pass
這裏我用的片段爲@auto_assign和@beartype和我自己的from_jsond。
import inspect
from typing import Any
_JSON_READABLE = [str, list, dict, Any]
def _from_jsond(cls, json_dict):
'''
Entity specific conversion of string dictionary to entity.
The json_dict is a dict of string, lists and other dicts as typically encoded in a JSON.
'''
kwargs = {}
init_parameters = inspect.signature(cls.__init__).parameters
for key, val in json_dict.items():
if key in init_parameters.keys():
if init_parameters[key].annotation in _JSON_READABLE:
kwargs[key] = val
else:
if hasattr(init_parameters[key].annotation, 'from_jsond'):
kwargs[key] = init_parameters[key].annotation.from_jsond(val)
else:
raise TypeError('No method to unserialize type "' + init_parameters[key].annotation.__name__ + '"')
else:
raise AttributeError('Class "' + cls.__name__ + '" does not accept attribute "' + key + '"')
return cls(**kwargs)
def from_jsond(cls):
''' Wrapper to add _from_jsonlike to cls as classmethod '''
cls.from_jsonlike = classmethod(_from_jsond)
return cls
繼承可能最有可能進一步減少它,但我不知道是否值得的麻煩和足夠穩定。意見和經驗,歡迎:)