diff --git a/src/Twilio/Converters/CustomConverters.cs b/src/Twilio/Converters/CustomConverters.cs index 448793732..268ee62fc 100644 --- a/src/Twilio/Converters/CustomConverters.cs +++ b/src/Twilio/Converters/CustomConverters.cs @@ -29,6 +29,19 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + if (reader.TokenType == JsonToken.Date) + { + var dt = ConvertToDateTime(reader.Value); + if (objectType == typeof(List)) + { + return new List { dt }; + } + return dt; + } if (reader.TokenType == JsonToken.StartArray) { var dateTimes = new List(); @@ -42,6 +55,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist dateTimes.Add(dateTime); } } + else if (reader.TokenType == JsonToken.Date) + { + dateTimes.Add(ConvertToDateTime(reader.Value)); + } else if (reader.TokenType == JsonToken.EndArray) { return dateTimes; @@ -58,6 +75,15 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist throw new JsonSerializationException("Failed to deserialize DateTime."); } + private static DateTime ConvertToDateTime(object value) + { + if (value is DateTime dt) + return dt; + if (value is DateTimeOffset dto) + return dto.DateTime; + throw new JsonSerializationException($"Cannot convert {value?.GetType()} to DateTime."); + } + public override bool CanConvert(Type objectType) { return objectType == typeof(DateTime?) || objectType ==typeof(List); diff --git a/test/Twilio.Test/Converters/DateTimeConverterTest.cs b/test/Twilio.Test/Converters/DateTimeConverterTest.cs new file mode 100644 index 000000000..055931cb8 --- /dev/null +++ b/test/Twilio.Test/Converters/DateTimeConverterTest.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using NUnit.Framework; +using Twilio.Converters; + +namespace Twilio.Tests.Converters +{ + [TestFixture] + public class DateTimeConverterTest + { + private class SingleDateModel + { + [JsonConverter(typeof(DateTimeConverter))] + public DateTime? Date { get; set; } + } + + private class DateListModel + { + [JsonConverter(typeof(DateTimeConverter))] + public List Dates { get; set; } + } + + [Test] + public void TestDeserializeNullToken() + { + var json = "{\"Date\": null}"; + var result = JsonConvert.DeserializeObject(json); + Assert.IsNull(result.Date); + } + + [Test] + public void TestDeserializeDateToken() + { + var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.DateTime }; + var json = "{\"Date\": \"2024-06-15T10:30:00Z\"}"; + var result = JsonConvert.DeserializeObject(json, settings); + Assert.IsNotNull(result.Date); + Assert.AreEqual(2024, result.Date.Value.Year); + Assert.AreEqual(6, result.Date.Value.Month); + Assert.AreEqual(15, result.Date.Value.Day); + } + + [Test] + public void TestDeserializeDateTimeOffsetToken() + { + var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.DateTimeOffset }; + var json = "{\"Date\": \"2024-06-15T10:30:00Z\"}"; + var result = JsonConvert.DeserializeObject(json, settings); + Assert.IsNotNull(result.Date); + Assert.AreEqual(2024, result.Date.Value.Year); + Assert.AreEqual(6, result.Date.Value.Month); + Assert.AreEqual(15, result.Date.Value.Day); + } + + [Test] + public void TestDeserializeStringToken() + { + var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None }; + var json = "{\"Date\": \"2024-06-15T10:30:00Z\"}"; + var result = JsonConvert.DeserializeObject(json, settings); + Assert.IsNotNull(result.Date); + Assert.AreEqual(2024, result.Date.Value.Year); + } + + [Test] + public void TestDeserializeArrayOfDateStrings() + { + var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None }; + var json = "{\"Dates\": [\"2024-01-01T00:00:00Z\", \"2024-12-31T00:00:00Z\"]}"; + var result = JsonConvert.DeserializeObject(json, settings); + Assert.AreEqual(2, result.Dates.Count); + Assert.AreEqual(1, result.Dates[0].Month); + Assert.AreEqual(12, result.Dates[1].Month); + } + + [Test] + public void TestDeserializeArrayOfDateTokens() + { + var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.DateTime }; + var json = "{\"Dates\": [\"2024-01-01T00:00:00Z\", \"2024-12-31T00:00:00Z\"]}"; + var result = JsonConvert.DeserializeObject(json, settings); + Assert.AreEqual(2, result.Dates.Count); + Assert.AreEqual(1, result.Dates[0].Month); + Assert.AreEqual(12, result.Dates[1].Month); + } + + [Test] + public void TestDeserializeArrayOfDateTimeOffsetTokens() + { + var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.DateTimeOffset }; + var json = "{\"Dates\": [\"2024-01-01T00:00:00Z\", \"2024-12-31T00:00:00Z\"]}"; + var result = JsonConvert.DeserializeObject(json, settings); + Assert.AreEqual(2, result.Dates.Count); + Assert.AreEqual(1, result.Dates[0].Month); + Assert.AreEqual(12, result.Dates[1].Month); + } + + [Test] + public void TestDeserializeInvalidTokenThrows() + { + var json = "{\"Date\": 12345}"; + Assert.Throws(() => + JsonConvert.DeserializeObject(json)); + } + } +}