|
import datetime |
|
import logging |
|
import re |
|
|
|
import omagent_core.engine.http.models as http_models |
|
import six |
|
from omagent_core.engine.configuration.configuration import Configuration |
|
from omagent_core.engine.http import rest |
|
from requests.structures import CaseInsensitiveDict |
|
|
|
logger = logging.getLogger(Configuration.get_logging_formatted_name(__name__)) |
|
|
|
|
|
class ObjectMapper(object): |
|
PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types |
|
NATIVE_TYPES_MAPPING = { |
|
"int": int, |
|
"long": int if six.PY3 else long, |
|
"float": float, |
|
"str": str, |
|
"bool": bool, |
|
"date": datetime.date, |
|
"datetime": datetime.datetime, |
|
"object": object, |
|
} |
|
|
|
def to_json(self, obj): |
|
|
|
if obj is None: |
|
return None |
|
elif isinstance(obj, self.PRIMITIVE_TYPES): |
|
return obj |
|
elif isinstance(obj, list): |
|
return [self.to_json(sub_obj) for sub_obj in obj] |
|
elif isinstance(obj, tuple): |
|
return tuple(self.to_json(sub_obj) for sub_obj in obj) |
|
elif isinstance(obj, (datetime.datetime, datetime.date)): |
|
return obj.isoformat() |
|
|
|
if isinstance(obj, dict) or isinstance(obj, CaseInsensitiveDict): |
|
obj_dict = obj |
|
else: |
|
|
|
|
|
|
|
|
|
|
|
if hasattr(obj, "attribute_map") and hasattr(obj, "swagger_types"): |
|
obj_dict = { |
|
obj.attribute_map[attr]: getattr(obj, attr) |
|
for attr, _ in six.iteritems(obj.swagger_types) |
|
if getattr(obj, attr) is not None |
|
} |
|
else: |
|
obj_dict = { |
|
name: getattr(obj, name) |
|
for name in vars(obj) |
|
if getattr(obj, name) is not None |
|
} |
|
|
|
return {key: self.to_json(val) for key, val in six.iteritems(obj_dict)} |
|
|
|
def from_json(self, data, klass): |
|
return self.__deserialize(data, klass) |
|
|
|
def __deserialize(self, data, klass): |
|
if data is None: |
|
return None |
|
|
|
if type(klass) == str: |
|
if klass.startswith("list["): |
|
sub_kls = re.match(r"list\[(.*)\]", klass).group(1) |
|
return [self.__deserialize(sub_data, sub_kls) for sub_data in data] |
|
|
|
if klass.startswith("dict("): |
|
sub_kls = re.match(r"dict\(([^,]*), (.*)\)", klass).group(2) |
|
return { |
|
k: self.__deserialize(v, sub_kls) for k, v in six.iteritems(data) |
|
} |
|
|
|
|
|
if klass in self.NATIVE_TYPES_MAPPING: |
|
klass = self.NATIVE_TYPES_MAPPING[klass] |
|
else: |
|
klass = getattr(http_models, klass) |
|
|
|
if klass in self.PRIMITIVE_TYPES: |
|
return self.__deserialize_primitive(data, klass) |
|
elif klass == object: |
|
return self.__deserialize_object(data) |
|
elif klass == datetime.date: |
|
return self.__deserialize_date(data) |
|
elif klass == datetime.datetime: |
|
return self.__deserialize_datatime(data) |
|
else: |
|
return self.__deserialize_model(data, klass) |
|
|
|
def __deserialize_primitive(self, data, klass): |
|
"""Deserializes string to primitive type. |
|
|
|
:param data: str. |
|
:param klass: class literal. |
|
|
|
:return: int, long, float, str, bool. |
|
""" |
|
try: |
|
if klass == str and type(data) == bytes: |
|
return self.__deserialize_bytes_to_str(data) |
|
return klass(data) |
|
except UnicodeEncodeError: |
|
return six.text_type(data) |
|
except TypeError: |
|
return data |
|
|
|
def __deserialize_bytes_to_str(self, data): |
|
return data.decode("utf-8") |
|
|
|
def __deserialize_object(self, value): |
|
"""Return a original value. |
|
|
|
:return: object. |
|
""" |
|
return value |
|
|
|
def __deserialize_date(self, string): |
|
"""Deserializes string to date. |
|
|
|
:param string: str. |
|
:return: date. |
|
""" |
|
try: |
|
from dateutil.parser import parse |
|
|
|
return parse(string).date() |
|
except ImportError: |
|
return string |
|
except ValueError: |
|
raise rest.ApiException( |
|
status=0, reason="Failed to parse `{0}` as date object".format(string) |
|
) |
|
|
|
def __deserialize_datatime(self, string): |
|
"""Deserializes string to datetime. |
|
|
|
The string should be in iso8601 datetime format. |
|
|
|
:param string: str. |
|
:return: datetime. |
|
""" |
|
try: |
|
from dateutil.parser import parse |
|
|
|
return parse(string) |
|
except ImportError: |
|
return string |
|
except ValueError: |
|
raise rest.ApiException( |
|
status=0, |
|
reason=("Failed to parse `{0}` as datetime object".format(string)), |
|
) |
|
|
|
def __hasattr(self, object, name): |
|
return name in object.__class__.__dict__ |
|
|
|
def __deserialize_model(self, data, klass): |
|
if not klass.swagger_types and not self.__hasattr( |
|
klass, "get_real_child_model" |
|
): |
|
return data |
|
|
|
kwargs = {} |
|
if klass.swagger_types is not None: |
|
for attr, attr_type in six.iteritems(klass.swagger_types): |
|
if ( |
|
data is not None |
|
and klass.attribute_map[attr] in data |
|
and isinstance(data, (list, dict)) |
|
): |
|
value = data[klass.attribute_map[attr]] |
|
kwargs[attr] = self.__deserialize(value, attr_type) |
|
|
|
instance = klass(**kwargs) |
|
|
|
if ( |
|
isinstance(instance, dict) |
|
and klass.swagger_types is not None |
|
and isinstance(data, dict) |
|
): |
|
for key, value in data.items(): |
|
if key not in klass.swagger_types: |
|
instance[key] = value |
|
if self.__hasattr(instance, "get_real_child_model"): |
|
klass_name = instance.get_real_child_model(data) |
|
if klass_name: |
|
instance = self.__deserialize(data, klass_name) |
|
return instance |
|
|