diff --git a/src/StronglyTypedIds.Templates/int-full.typedid b/src/StronglyTypedIds.Templates/int-full.typedid index ec8031bb..1d1ed672 100644 --- a/src/StronglyTypedIds.Templates/int-full.typedid +++ b/src/StronglyTypedIds.Templates/int-full.typedid @@ -88,7 +88,20 @@ public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); + { +#if NET6_0_OR_GREATER + if (options.NumberHandling.HasFlag(global::System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString) && reader.TokenType == global::System.Text.Json.JsonTokenType.String) + { + var str = reader.GetString(); + + if (!string.IsNullOrEmpty(str) && PLACEHOLDERID.TryParse(str, null, out var val)) + return val; + + return default; + } +#endif + return new PLACEHOLDERID(reader.GetInt32()); + } public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WriteNumberValue(value.Value); diff --git a/src/StronglyTypedIds.Templates/long-full.typedid b/src/StronglyTypedIds.Templates/long-full.typedid index c63c34af..39e0b940 100644 --- a/src/StronglyTypedIds.Templates/long-full.typedid +++ b/src/StronglyTypedIds.Templates/long-full.typedid @@ -88,7 +88,20 @@ public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); + { +#if NET6_0_OR_GREATER + if (options.NumberHandling.HasFlag(global::System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString) && reader.TokenType == global::System.Text.Json.JsonTokenType.String) + { + var str = reader.GetString(); + + if (!string.IsNullOrEmpty(str) && PLACEHOLDERID.TryParse(str, null, out var val)) + return val; + + return default; + } +#endif + return new PLACEHOLDERID(reader.GetInt64()); + } public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WriteNumberValue(value.Value); diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index 06b6c398..73bf58df 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -90,7 +90,20 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); + { + #if NET6_0_OR_GREATER + if (options.NumberHandling.HasFlag(global::System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString) && reader.TokenType == global::System.Text.Json.JsonTokenType.String) + { + var str = reader.GetString(); + + if (!string.IsNullOrEmpty(str) && PLACEHOLDERID.TryParse(str, null, out var val)) + return val; + + return default; + } + #endif + return new PLACEHOLDERID(reader.GetInt32()); + } public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WriteNumberValue(value.Value); diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index fe0cf17a..64e99a41 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -90,7 +90,20 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt64()); + { + #if NET6_0_OR_GREATER + if (options.NumberHandling.HasFlag(global::System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString) && reader.TokenType == global::System.Text.Json.JsonTokenType.String) + { + var str = reader.GetString(); + + if (!string.IsNullOrEmpty(str) && PLACEHOLDERID.TryParse(str, null, out var val)) + return val; + + return default; + } + #endif + return new PLACEHOLDERID(reader.GetInt64()); + } public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WriteNumberValue(value.Value); diff --git a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs index dd73bae7..249f1b51 100644 --- a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs @@ -120,7 +120,7 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() } } """; - Assert.Equal(serialized, expected); + Assert.Equal(expected, serialized); var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); @@ -128,6 +128,33 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() Assert.True(deserialized.Values.ContainsKey(key)); Assert.Equal("My Value", deserialized.Values[key]); } + + [Fact] + public void CanDeserializeWhenIntIsStoredAsAString_WithSystemTextJsonProvider() + { + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + }; + + var key = "My Key"; + + var serialized = $$""" + { + "values": { + "My Key": "123" + } + } + """; + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal(new IntId(123), deserialized.Values[key]); + } #endif [Fact] @@ -589,6 +616,11 @@ internal class TypeWithDictionaryKeys public Dictionary Values { get; set; } } + internal class DictionaryWithTypeValue + { + public Dictionary Values { get; set; } + } + internal record ToSerialize { public ConvertersIntId Id { get; set; } diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index 45805b94..bb261dd4 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -119,7 +119,7 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() } } """; - Assert.Equal(serialized, expected); + Assert.Equal(expected, serialized); var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); @@ -127,6 +127,33 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() Assert.True(deserialized.Values.ContainsKey(key)); Assert.Equal("My Value", deserialized.Values[key]); } + + [Fact] + public void CanDeserializeWhenLongIsStoredAsAString_WithSystemTextJsonProvider() + { + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + }; + + var key = "My Key"; + + var serialized = $$""" + { + "values": { + "My Key": "123" + } + } + """; + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal(new LongId(123), deserialized.Values[key]); + } #endif [Fact] @@ -571,6 +598,11 @@ internal class TypeWithDictionaryKeys public Dictionary Values { get; set; } } + internal class DictionaryWithTypeValue + { + public Dictionary Values { get; set; } + } + internal record ToSerialize { public ConvertersLongId Id { get; set; }