From 9ccd477aa7bc227836704fcfdac8fc52ef220d96 Mon Sep 17 00:00:00 2001 From: Martin Machacek Date: Thu, 18 Jul 2024 13:11:16 +0200 Subject: [PATCH] Use invariant culture for (de)serialization --- .../form/FormSerializationWriter.cs | 3 + src/serialization/json/JsonParseNode.cs | 22 +- .../form/FormSerializationWriterTests.cs | 2 +- .../json/Converters/JsonDateConverter.cs | 29 +++ .../Converters/JsonDateTimeOffsetConverter.cs | 28 +++ .../json/Converters/JsonTimeConverter.cs | 29 +++ .../serialization/json/JsonParseNodeTests.cs | 210 ++++++++++++++++++ 7 files changed, 311 insertions(+), 12 deletions(-) create mode 100644 tests/serialization/json/Converters/JsonDateConverter.cs create mode 100644 tests/serialization/json/Converters/JsonDateTimeOffsetConverter.cs create mode 100644 tests/serialization/json/Converters/JsonTimeConverter.cs diff --git a/src/serialization/form/FormSerializationWriter.cs b/src/serialization/form/FormSerializationWriter.cs index 137d5d35..93a9325b 100644 --- a/src/serialization/form/FormSerializationWriter.cs +++ b/src/serialization/form/FormSerializationWriter.cs @@ -86,6 +86,9 @@ private void WriteAnyValue(string? key, object value) case IEnumerable coll: WriteCollectionOfPrimitiveValues(key, coll); break; + case byte[] coll: + WriteByteArrayValue(key, coll); + break; case IParsable: throw new InvalidOperationException("Form serialization does not support nested objects."); default: diff --git a/src/serialization/json/JsonParseNode.cs b/src/serialization/json/JsonParseNode.cs index 3b400150..7a107ee3 100644 --- a/src/serialization/json/JsonParseNode.cs +++ b/src/serialization/json/JsonParseNode.cs @@ -177,14 +177,14 @@ public JsonParseNode(JsonElement node, KiotaJsonSerializationContext jsonSeriali /// A value public Date? GetDateValue() { - var dateString = _jsonNode.GetString(); - if(string.IsNullOrEmpty(dateString)) + if(_jsonNode.ValueKind != JsonValueKind.String) return null; - if(DateTime.TryParse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result)) - return new Date(result); - - return _jsonNode.Deserialize(_jsonSerializerContext.Date); + if(TryGetUsingTypeInfo(_jsonNode, _jsonSerializerContext.Date, out var date)) + return date; + else if(DateTime.TryParse(_jsonNode.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dt)) + return new Date(dt); + else return null; } /// @@ -193,14 +193,14 @@ public JsonParseNode(JsonElement node, KiotaJsonSerializationContext jsonSeriali /// A value public Time? GetTimeValue() { - var dateString = _jsonNode.GetString(); - if(string.IsNullOrEmpty(dateString)) + if(_jsonNode.ValueKind != JsonValueKind.String) return null; - if(DateTime.TryParse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result)) + if(TryGetUsingTypeInfo(_jsonNode, _jsonSerializerContext.Time, out var time)) + return time; + if(DateTime.TryParse(_jsonNode.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result)) return new Time(result); - - return _jsonNode.Deserialize(_jsonSerializerContext.Time); + else return null; } /// diff --git a/tests/serialization/form/FormSerializationWriterTests.cs b/tests/serialization/form/FormSerializationWriterTests.cs index ded84356..45822417 100644 --- a/tests/serialization/form/FormSerializationWriterTests.cs +++ b/tests/serialization/form/FormSerializationWriterTests.cs @@ -414,7 +414,7 @@ public void WriteAdditionalData_AreWrittenCorrectly() var serializedString = reader.ReadToEnd(); // Assert - Assert.Equal("prop1=value1&prop2=2&prop3=true&prop4=2.25&prop5=3.14&prop6=4&prop7=5&prop8=2024-11-30T15%3A35%3A45.9870000%2B03%3A00&prop9=2024-11-30&prop10=23%3A46%3A59&prop11=P756DT4H6M8.01S&prop12=System.Byte%5B%5D&prop13=3adeb301-58f1-45c5-b820-ae5f4af13c89&prop14=127", serializedString); + Assert.Equal("prop1=value1&prop2=2&prop3=true&prop4=2.25&prop5=3.14&prop6=4&prop7=5&prop8=2024-11-30T15%3A35%3A45.9870000%2B03%3A00&prop9=2024-11-30&prop10=23%3A46%3A59&prop11=P756DT4H6M8.01S&prop12=AgQG&prop13=3adeb301-58f1-45c5-b820-ae5f4af13c89&prop14=127", serializedString); } [Fact] diff --git a/tests/serialization/json/Converters/JsonDateConverter.cs b/tests/serialization/json/Converters/JsonDateConverter.cs new file mode 100644 index 00000000..8d722992 --- /dev/null +++ b/tests/serialization/json/Converters/JsonDateConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Kiota.Abstractions; + +namespace Microsoft.Kiota.Serialization.Json.Tests.Converters; + +/// +/// Converts a Date object or value to/from JSON. +/// +public class JsonDateConverter : JsonConverter +{ + /// + public override Date Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => reader.TokenType == JsonTokenType.Null + ? new Date() + : ReadInternal(ref reader); + + /// + public override void Write(Utf8JsonWriter writer, Date value, JsonSerializerOptions options) + => WriteInternal(writer, value); + + private static Date ReadInternal(ref Utf8JsonReader reader) + => new Date(DateTime.ParseExact(reader.GetString()!, "dd---MM---yyyy", CultureInfo.InvariantCulture)); + + private static void WriteInternal(Utf8JsonWriter writer, Date value) + => writer.WriteStringValue($"{value.Day}---{value.Month}---{value.Year}"); +} \ No newline at end of file diff --git a/tests/serialization/json/Converters/JsonDateTimeOffsetConverter.cs b/tests/serialization/json/Converters/JsonDateTimeOffsetConverter.cs new file mode 100644 index 00000000..f23b4b25 --- /dev/null +++ b/tests/serialization/json/Converters/JsonDateTimeOffsetConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Kiota.Serialization.Json.Tests.Converters; + +/// +/// Converts a DateTimeOffset object or value to/from JSON. +/// +public class JsonDateTimeOffsetConverter : JsonConverter +{ + /// + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => reader.TokenType == JsonTokenType.Null + ? new DateTimeOffset() + : ReadInternal(ref reader); + + /// + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + => WriteInternal(writer, value); + + private static DateTimeOffset ReadInternal(ref Utf8JsonReader reader) + => DateTimeOffset.ParseExact(reader.GetString()!, "dd__MM__yyyyTHH_mm_ssZ", CultureInfo.InvariantCulture); + + private static void WriteInternal(Utf8JsonWriter writer, DateTimeOffset value) + => writer.WriteStringValue(value.ToString("dd__MM__yyyyTHH_mm_ssZ")); +} diff --git a/tests/serialization/json/Converters/JsonTimeConverter.cs b/tests/serialization/json/Converters/JsonTimeConverter.cs new file mode 100644 index 00000000..4e0cdc87 --- /dev/null +++ b/tests/serialization/json/Converters/JsonTimeConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Kiota.Abstractions; + +namespace Microsoft.Kiota.Serialization.Json.Tests.Converters; + +/// +/// Converts a Time object or value to/from JSON. +/// +public class JsonTimeConverter : JsonConverter