diff --git a/msrest/serialization.py b/msrest/serialization.py index 547623a..a18bebe 100644 --- a/msrest/serialization.py +++ b/msrest/serialization.py @@ -113,31 +113,38 @@ class Model(object): return base._subtype_map return {} + @classmethod + def _flatten_subtype(cls, key, objects): + if not '_subtype_map' in cls.__dict__: + return {} + result = dict(cls._subtype_map[key]) + for valuetype in cls._subtype_map[key].values(): + result.update(objects[valuetype]._flatten_subtype(key, objects)) + return result + @classmethod def _classify(cls, response, objects): """Check the class _subtype_map for any child classes. - We want to ignore any inheirited _subtype_maps. + We want to ignore any inherited _subtype_maps. + Remove the polymorphic key from the initial data. """ - try: - map = cls.__dict__.get('_subtype_map', {}) + for subtype_key in cls.__dict__.get('_subtype_map', {}).keys(): + subtype_value = None - for _type, _classes in map.items(): - classification = response.get(_type) - try: - return objects[_classes[classification]] - except KeyError: - pass + rest_api_response_key = _decode_attribute_map_key(cls._attribute_map[subtype_key]['key']) + subtype_value = response.pop(rest_api_response_key, None) or response.pop(subtype_key, None) + if subtype_value: + flatten_mapping_type = cls._flatten_subtype(subtype_key, objects) + return objects[flatten_mapping_type[subtype_value]] + return cls - for c in _classes: - try: - _cls = objects[_classes[c]] - return _cls._classify(response, objects) - except (KeyError, TypeError): - continue - raise TypeError("Object cannot be classified futher.") - except AttributeError: - raise TypeError("Object cannot be classified futher.") +def _decode_attribute_map_key(key): + """This decode a key in an _attribute_map to the actual key we want to look at + inside the received data. + :param str key: A key string from the generated code + """ + return key.replace('\\.', '.') def _convert_to_datatype(data, data_type, localtypes): if data is None: @@ -157,6 +164,7 @@ def _convert_to_datatype(data, data_type, localtypes): elif issubclass(data_obj, Enum): return data elif not isinstance(data, data_obj): + data_obj = data_obj._classify(data, localtypes) result = { key: _convert_to_datatype( data[key], @@ -195,7 +203,7 @@ class Serializer(object): "unique": lambda x, y: len(x) != len(set(x)), "multiple": lambda x, y: x % y != 0 } - flattten = re.compile(r"(?