From 4da582f1ad3fd6114c770eb47fdd0a69c03cdef7 Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 7 May 2019 19:43:39 +0800 Subject: [PATCH 1/3] =?UTF-8?q?add=20=E8=87=AA=E5=AE=9A=E4=B9=89key?= =?UTF-8?q?=E6=98=A0=E5=B0=84=EF=BC=8C=5F=5Finit=5F=5F=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=AF=BB=E5=8F=96json=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jsonModel.py | 92 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/jsonModel.py b/jsonModel.py index 2ce2a22..e908e6e 100644 --- a/jsonModel.py +++ b/jsonModel.py @@ -4,8 +4,10 @@ # everyone can use this code for any purpose. # ---------------------------------------------------------------------- +import json -def jsonModel(objectMap={}, listClassMap={}): + +def jsonModel(objectMap={}, listClassMap={}, customKeyMap={}): """ It is very easy to use ! @jsonModel(objectMap={"car": Car}, listClassMap={"pets": Dog}) @@ -14,41 +16,106 @@ def jsonModel(objectMap={}, listClassMap={}): or @jsonModel() """ + def decorate(cls): + __origin_init__ = None + + def __hack_init__(self, *args, **kwargs): + # exclude self + expect_arg_count = __origin_init__.__code__.co_argcount - 1 + varnames = __origin_init__.__code__.co_varnames + co_flags = __origin_init__.__code__.co_flags + is_args = co_flags & 0b100 != 0 + is_kwargs = co_flags & 0b1000 != 0 + + if is_args and is_kwargs: + __origin_init__(self, *args, **kwargs) + return + if is_args and not is_kwargs: + __origin_init__(self, *args) + return + if is_kwargs and not is_args: + __origin_init__(self, **kwargs) + return + + # no extra json param + if expect_arg_count == (len(args) + len(kwargs)): + __origin_init__(self, *args, **kwargs) + return + + # extra json param or exception + if expect_arg_count + 1 == (len(args) + len(kwargs)): + # find json param in kwargs + json_key = None + json_data = None + for (key, val) in kwargs.iteritems(): + if key not in varnames: + json_key = key + json_data = val + break + # find json param in args + if not json_data and len(args) > 0: + json_data = args[-1] + # check json param type + if isinstance(json_data, basestring): + json_data = json.loads(json_data) + if not isinstance(json_data, dict): + raise Exception("[error] invalid parameter or json format, expect dict or json string") + + real_args = args + real_kwargs = kwargs + if json_key: + real_kwargs.pop(json_key) + else: + real_args = args[0:expect_arg_count] + __origin_init__(self, *real_args, **real_kwargs) + fromJson(self, json_data) + return + + # incorrect param count + raise Exception("[error] invalid parameter count, expect " + str(expect_arg_count) + ", got " + str(len(args))) + def fromJson(self, data): """ json key_value model""" for key in self.__dict__: - if key in data: - if isinstance(data[key], dict) and key in objectMap: + custom_key = key + if key in customKeyMap: + custom_key = customKeyMap[key] + if custom_key in data: + if isinstance(data[custom_key], dict) and key in objectMap: obj = self.__dict__[key] = objectMap[key]() - obj.fromJson(data[key]) - elif isinstance(data[key], (list, tuple)) and key in listClassMap: + obj.fromJson(data[custom_key]) + elif isinstance(data[custom_key], (list, tuple)) and key in listClassMap: tempList = [] - for item in data[key]: + for item in data[custom_key]: obj = listClassMap[key]() obj.fromJson(item) tempList.append(obj) self.__dict__[key] = tempList else: - self.__dict__[key] = data[key] + self.__dict__[key] = data[custom_key] else: - print("JsonModel log : " + key + " not in json data") + print("JsonModel log : [" + key + " --> " + custom_key + "] not in json data") def toKeyValue(self): """ model to json key_value """ tempDic = {} for key in self.__dict__: + custom_key = key + if key in customKeyMap: + custom_key = customKeyMap[key] + if key in objectMap: obj = self.__dict__[key] - tempDic[key] = obj.toKeyValue() + tempDic[custom_key] = obj.toKeyValue() elif key in listClassMap: tempList = [] for item in self.__dict__[key]: obj = item.toKeyValue() tempList.append(obj) - tempDic[key] = tempList + tempDic[custom_key] = tempList else: - tempDic[key] = self.__dict__[key] + tempDic[custom_key] = self.__dict__[key] return tempDic @classmethod @@ -71,10 +138,13 @@ def objectArrayToJsonArray(className, objectList): tempList.append(obj.toKeyValue()) return tempList + __origin_init__ = cls.__init__ + cls.__init__ = __hack_init__ cls.fromJson = fromJson cls.toKeyValue = toKeyValue cls.objectArrayFromJsonArray = objectArrayFromJsonArray cls.objectArrayToJsonArray = objectArrayToJsonArray return cls + return decorate From 7c643ab2bfcfd5d199af526dd1f26a48aef3f263 Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 7 May 2019 21:08:05 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix=20=E5=8F=AF=E9=80=89=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E8=A7=A3=E6=9E=90crash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jsonModel.py | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/jsonModel.py b/jsonModel.py index e908e6e..e76bfe7 100644 --- a/jsonModel.py +++ b/jsonModel.py @@ -22,12 +22,16 @@ def decorate(cls): def __hack_init__(self, *args, **kwargs): # exclude self - expect_arg_count = __origin_init__.__code__.co_argcount - 1 + input_count = len(args) + len(kwargs) + default_var_count = len(__origin_init__.__defaults__) + min_arg_count = __origin_init__.__code__.co_argcount - default_var_count - 1 + max_arg_count = __origin_init__.__code__.co_argcount varnames = __origin_init__.__code__.co_varnames co_flags = __origin_init__.__code__.co_flags is_args = co_flags & 0b100 != 0 is_kwargs = co_flags & 0b1000 != 0 + # variable parameters unsupported, consider using `fromJson` in `__init__` directly if is_args and is_kwargs: __origin_init__(self, *args, **kwargs) return @@ -39,21 +43,20 @@ def __hack_init__(self, *args, **kwargs): return # no extra json param - if expect_arg_count == (len(args) + len(kwargs)): + if input_count == min_arg_count: __origin_init__(self, *args, **kwargs) return - # extra json param or exception - if expect_arg_count + 1 == (len(args) + len(kwargs)): - # find json param in kwargs - json_key = None + # check extra json param or exception + if input_count == max_arg_count: + # lookup json param in kwargs json_data = None for (key, val) in kwargs.iteritems(): if key not in varnames: - json_key = key json_data = val + kwargs.pop(key) break - # find json param in args + # lookup json param in args if not json_data and len(args) > 0: json_data = args[-1] # check json param type @@ -61,19 +64,32 @@ def __hack_init__(self, *args, **kwargs): json_data = json.loads(json_data) if not isinstance(json_data, dict): raise Exception("[error] invalid parameter or json format, expect dict or json string") + __origin_init__(self, *args, **kwargs) + fromJson(self, json_data) + return - real_args = args - real_kwargs = kwargs - if json_key: - real_kwargs.pop(json_key) - else: - real_args = args[0:expect_arg_count] - __origin_init__(self, *real_args, **real_kwargs) + # lookup extra json param or exception + if min_arg_count < input_count < max_arg_count: + # lookup json param in kwargs + json_data = None + for (key, val) in kwargs.iteritems(): + if key not in varnames: + json_data = val + kwargs.pop(key) + break + if not json_data: + __origin_init__(self, *args, **kwargs) + return + if isinstance(json_data, basestring): + json_data = json.loads(json_data) + if not isinstance(json_data, dict): + raise Exception("[error] invalid parameter or json format, expect dict or json string") + __origin_init__(self, *args, **kwargs) fromJson(self, json_data) return # incorrect param count - raise Exception("[error] invalid parameter count, expect " + str(expect_arg_count) + ", got " + str(len(args))) + raise Exception("[error] invalid parameter count, expect " + str(min_arg_count) + ", got " + str(len(args))) def fromJson(self, data): """ json key_value model""" From ac0caa416dc736e594be3407bf8a706fefb2e913 Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 7 May 2019 22:13:04 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix=20=E5=8E=9F=E7=94=9F=5F=5Finit=5F=5F?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E6=8A=BD=E7=A6=BB=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=97=A0=E5=85=A5=E5=8F=82=E6=97=B6execption?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jsonModel.py | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/jsonModel.py b/jsonModel.py index e76bfe7..af67f8e 100644 --- a/jsonModel.py +++ b/jsonModel.py @@ -22,8 +22,10 @@ def decorate(cls): def __hack_init__(self, *args, **kwargs): # exclude self - input_count = len(args) + len(kwargs) - default_var_count = len(__origin_init__.__defaults__) + arg_length = 0 if not args else len(args) + kwargs_length = 0 if not kwargs else len(kwargs) + input_count = arg_length + kwargs_length + default_var_count = 0 if not __origin_init__.__defaults__ else len(__origin_init__.__defaults__) min_arg_count = __origin_init__.__code__.co_argcount - default_var_count - 1 max_arg_count = __origin_init__.__code__.co_argcount varnames = __origin_init__.__code__.co_varnames @@ -32,19 +34,13 @@ def __hack_init__(self, *args, **kwargs): is_kwargs = co_flags & 0b1000 != 0 # variable parameters unsupported, consider using `fromJson` in `__init__` directly - if is_args and is_kwargs: - __origin_init__(self, *args, **kwargs) - return - if is_args and not is_kwargs: - __origin_init__(self, *args) - return - if is_kwargs and not is_args: - __origin_init__(self, **kwargs) + if is_args or is_kwargs: + call_origin_init(self, *args, **kwargs) return # no extra json param if input_count == min_arg_count: - __origin_init__(self, *args, **kwargs) + call_origin_init(self, *args, **kwargs) return # check extra json param or exception @@ -57,14 +53,14 @@ def __hack_init__(self, *args, **kwargs): kwargs.pop(key) break # lookup json param in args - if not json_data and len(args) > 0: + if not json_data and arg_length > 0: json_data = args[-1] # check json param type if isinstance(json_data, basestring): json_data = json.loads(json_data) if not isinstance(json_data, dict): raise Exception("[error] invalid parameter or json format, expect dict or json string") - __origin_init__(self, *args, **kwargs) + call_origin_init(self, *args, **kwargs) fromJson(self, json_data) return @@ -78,18 +74,40 @@ def __hack_init__(self, *args, **kwargs): kwargs.pop(key) break if not json_data: - __origin_init__(self, *args, **kwargs) + call_origin_init(self, *args, **kwargs) return if isinstance(json_data, basestring): json_data = json.loads(json_data) if not isinstance(json_data, dict): raise Exception("[error] invalid parameter or json format, expect dict or json string") - __origin_init__(self, *args, **kwargs) + + call_origin_init(self, *args, **kwargs) fromJson(self, json_data) return # incorrect param count - raise Exception("[error] invalid parameter count, expect " + str(min_arg_count) + ", got " + str(len(args))) + raise Exception("[error] invalid parameter count, expect " + str(min_arg_count) + ", got " + str(arg_length)) + + def call_origin_init(self, *args, **kwargs): + co_flags = __origin_init__.__code__.co_flags + is_args = co_flags & 0b100 != 0 + is_kwargs = co_flags & 0b1000 != 0 + if is_args and is_kwargs: + __origin_init__(self, *args, **kwargs) + return + if is_args and not is_kwargs: + __origin_init__(self, *args) + return + if is_kwargs and not is_args: + __origin_init__(self, **kwargs) + return + + varnames = __origin_init__.__code__.co_varnames + has_param = (len(varnames) > 1) + if has_param: + __origin_init__(self, *args, **kwargs) + else: + __origin_init__(self) def fromJson(self, data): """ json key_value model"""