Repository: Azure/msrest-for-python

Issue:
Serialization for non-standard types yields incorrect output
Hi,

I am using the event grid client SDK in python to generate custom events. I have come across an issue I can't seem to solve without going away from the event grid SDK. 

The problem is that the event grid model serializer does not give me the correct output for when including types that are not the basic types. A simple reproducible example:

```
from azure.eventgrid.models import EventGridEvent
import datetime
import uuid

event=EventGridEvent(
            topic="test",
            id=uuid.uuid4(),
            subject="testUpdated",
            data={"time":datetime.datetime.now().replace(tzinfo=datetime.timezone.utc)},
            event_type="test.test",
            event_time=datetime.datetime.now().replace(tzinfo=datetime.timezone.utc),
            data_version=2.0,
)

print(event.serialize())
```

This would return

`
{'id': '3e02a22c-f327-4f62-af25-b71e0865888b',
 'topic': 'product',
 'subject': 'ProductUpdated',
 'data': {'time': '2020-09-07 10:37:08.348679+00:00'},
 'eventType': 'supplychain.product',
 'eventTime': '2020-09-07T10:37:08.348679Z',
 'dataVersion': '2.0'}
`

the serialize is not called by me in the code I actually use, but it looks like that is what is called behind the scenes when I send off the event. I want the datetime (the key "time" in the above example) to be serialized just as the parent-level "event_time". My problem is not only with datetime as in the current example, but also with decimals.

I guess this fits in this repo and not in the EventGrid SDK repo, but feel free to redirect me there.






Comments:

Patch:
diff --git a/msrest/serialization.py b/msrest/serialization.py
index f9037b9..378de20 100644
--- a/msrest/serialization.py
+++ b/msrest/serialization.py
@@ -953,6 +953,16 @@ class Serializer(object):
             return self.serialize_long(attr)
         if obj_type is unicode_str:
             return self.serialize_unicode(attr)
+        if obj_type is datetime.datetime:
+            return self.serialize_iso(attr)
+        if obj_type is datetime.date:
+            return self.serialize_date(attr)
+        if obj_type is datetime.time:
+            return self.serialize_time(attr)
+        if obj_type is datetime.timedelta:
+            return self.serialize_duration(attr)
+        if obj_type is decimal.Decimal:
+            return self.serialize_decimal(attr)
 
         # If it's a model or I know this dependency, serialize as a Model
         elif obj_type in self.dependencies.values() or isinstance(attr, Model):


Test patch:
diff --git a/tests/test_serialization.py b/tests/test_serialization.py
index ab04cfd..6837bad 100644
--- a/tests/test_serialization.py
+++ b/tests/test_serialization.py
@@ -25,6 +25,7 @@
 #
 #--------------------------------------------------------------------------
 
+from decimal import Decimal
 import sys
 import json
 import isodate
@@ -1395,6 +1396,42 @@ class TestRuntimeSerialized(unittest.TestCase):
             'data': {'id': u"\ua015"}
         }
 
+    def test_datetime_types_as_type_object(self):
+        """https://github.com/Azure/msrest-for-python/issues/223
+        """
+
+        class TestModel(Model):
+            _attribute_map = {'data': {'key': 'data', 'type': 'object'}}
+
+        m = TestModel(data = {
+            'datetime': isodate.parse_datetime('2012-02-24T00:53:52.780Z'),
+            'date': date(2019,5,1),
+            'time': time(11,12,13),
+            'timedelta': timedelta(56)
+        })
+        serialized = m.serialize()
+        assert serialized['data'] == {
+            'datetime': '2012-02-24T00:53:52.780Z',
+            'date': '2019-05-01',
+            'time': '11:12:13',
+            'timedelta': 'P56D'
+        }
+
+    def test_decimal_types_as_type_object(self):
+        """https://github.com/Azure/msrest-for-python/issues/223
+        """
+
+        class TestModel(Model):
+            _attribute_map = {'data': {'key': 'data', 'type': 'object'}}
+
+        m = TestModel(data = {
+            'decimal': Decimal('1.1'),
+        })
+        serialized = m.serialize()
+        assert serialized['data'] == {
+            'decimal': 1.1
+        }
+
     def test_json_with_xml_map(self):
         basic_json = {'age': 37, 'country': 'france'}