Repository: Azure/msrest-for-python

Issue:
Error when serializing flattened properties with null value as the container object
i found the msrest will report error when serializing flattened properties with null value as the container object, could you help to check? I tried to look at the msrest code, and seems the situation when 'data' is null is not handled in the last screenshot below. thanks.
![image](https://user-images.githubusercontent.com/6038235/78621314-e6cf1980-78b4-11ea-9316-58bee4dbbb38.png)
![image](https://user-images.githubusercontent.com/6038235/78621324-ef275480-78b4-11ea-94b3-29b6350b7218.png)
![image](https://user-images.githubusercontent.com/6038235/78621335-f64e6280-78b4-11ea-972b-b062f01efeab.png)


Comments:

Patch:
diff --git a/msrest/serialization.py b/msrest/serialization.py
index 27fb7e9..59187e1 100644
--- a/msrest/serialization.py
+++ b/msrest/serialization.py
@@ -1108,6 +1108,11 @@ def rest_key_extractor(attr, attr_desc, data):
             break
         working_key = _decode_attribute_map_key(dict_keys[0])
         working_data = working_data.get(working_key, data)
+        if working_data is None:
+            # If at any point while following flatten JSON path see None, it means
+            # that all properties under are None as well
+            # https://github.com/Azure/msrest-for-python/issues/197
+            return None
         key = '.'.join(dict_keys[1:])
 
     return working_data.get(key)
@@ -1123,6 +1128,11 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
             break
         working_key = _decode_attribute_map_key(dict_keys[0])
         working_data = attribute_key_case_insensitive_extractor(working_key, None, working_data)
+        if working_data is None:
+            # If at any point while following flatten JSON path see None, it means
+            # that all properties under are None as well
+            # https://github.com/Azure/msrest-for-python/issues/197
+            return None
         key = '.'.join(dict_keys[1:])
 
     if working_data:


Test patch:
diff --git a/tests/test_serialization.py b/tests/test_serialization.py
index 4b3f537..12a0042 100644
--- a/tests/test_serialization.py
+++ b/tests/test_serialization.py
@@ -1527,6 +1527,46 @@ class TestRuntimeDeserialized(unittest.TestCase):
         obj = TestObj.from_dict({'name': 'ab'})
         self.assertEqual('ab', obj.name)
 
+    def test_deserialize_flattening(self):
+        # https://github.com/Azure/msrest-for-python/issues/197
+
+        json_body = {
+            "properties" : {
+                "properties": None
+            }
+        }
+
+        class ComputeResource(Model):
+
+            _attribute_map = {
+                'properties': {'key': 'properties', 'type': 'VirtualMachine'},
+            }
+
+            def __init__(self, properties=None, **kwargs):
+                self.properties = properties
+
+        class VirtualMachine(Model):
+
+            _attribute_map = {
+                'virtual_machine_size': {'key': 'properties.virtualMachineSize', 'type': 'str'},
+                'ssh_port': {'key': 'properties.sshPort', 'type': 'int'},
+                'address': {'key': 'properties.address', 'type': 'str'},
+                'administrator_account': {'key': 'properties.administratorAccount', 'type': 'VirtualMachineSshCredentials'},
+            }
+
+            def __init__(self, **kwargs):
+                super(VirtualMachine, self).__init__(**kwargs)
+                self.virtual_machine_size = kwargs.get('virtual_machine_size', None)
+                self.ssh_port = kwargs.get('ssh_port', None)
+                self.address = kwargs.get('address', None)
+                self.administrator_account = kwargs.get('administrator_account', None)
+
+        d = Deserializer({
+            'ComputeResource': ComputeResource,
+            'VirtualMachine': VirtualMachine,
+        })
+        response = d(ComputeResource, json.dumps(json_body), 'application/json')
+
     def test_deserialize_storage(self):
         StorageAccount = storage_models.StorageAccount