From 839278673dbabcc2803c91027884b3145da600c2 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Wed, 12 May 2021 16:49:36 -0500 Subject: [PATCH 1/3] Fix trimming issue with extension data --- .../System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 500a0f35bbb0cf..2d444e9d0c9bd7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -389,7 +389,7 @@ internal bool ReadJsonAndAddExtensionProperty( else { // Slower path for non-generic types that implement IDictionary. - converter = JsonMetadataServices.ObjectConverter; + converter = Options.GetConverterInternal(JsonTypeInfo.ObjectType); } if (!converter.TryReadAsObject(ref reader, Options, ref state, out object? value)) From d4caa2bee9fac9b800db00841bcc033aecf1f56f Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Thu, 13 May 2021 10:13:45 -0500 Subject: [PATCH 2/3] Remove ref to JsonMetadataServices; fix issue with custom JsonElement converter on read --- .../Metadata/JsonPropertyInfo.cs | 63 +++++++++---------- .../Serialization/ExtensionDataTests.cs | 2 +- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 2d444e9d0c9bd7..732cff7b0ee61f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -368,57 +368,56 @@ internal bool ReadJsonAndAddExtensionProperty( { object propValue = GetValueAsObject(obj)!; - if (propValue is IDictionary dictionaryObject) + if (propValue is IDictionary dictionaryObjectValue) { - // Handle case where extension property is System.Object-based. - if (reader.TokenType == JsonTokenType.Null) { // A null JSON value is treated as a null object reference. - dictionaryObject[state.Current.JsonPropertyNameAsString!] = null; + dictionaryObjectValue[state.Current.JsonPropertyNameAsString!] = null; } else { - JsonConverter converter; - JsonTypeInfo? dictionaryValueInfo = RuntimeTypeInfo.ElementTypeInfo; - if (dictionaryValueInfo != null) - { - // Fast path when there is a generic type such as Dictionary. - converter = dictionaryValueInfo.PropertyInfoForTypeInfo.ConverterBase; - } - else - { - // Slower path for non-generic types that implement IDictionary. - converter = Options.GetConverterInternal(JsonTypeInfo.ObjectType); - } - - if (!converter.TryReadAsObject(ref reader, Options, ref state, out object? value)) - { - return false; - } - - dictionaryObject[state.Current.JsonPropertyNameAsString!] = value; + JsonConverter converter = (JsonConverter)GetDictionaryValueConverter(JsonTypeInfo.ObjectType); + object value = converter.Read(ref reader, JsonTypeInfo.ObjectType, Options); + dictionaryObjectValue[state.Current.JsonPropertyNameAsString!] = value; } } - else if (propValue is IDictionary dictionaryJsonElement) + else if (propValue is IDictionary dictionaryElementValue) { - JsonConverter converter = JsonMetadataServices.JsonElementConverter; - if (!converter.TryRead(ref reader, typeof(JsonElement), Options, ref state, out JsonElement value)) - { - return false; - } - - dictionaryJsonElement[state.Current.JsonPropertyNameAsString!] = value; + Type elementType = typeof(JsonElement); + JsonConverter converter = (JsonConverter)GetDictionaryValueConverter(elementType); + JsonElement value = converter.Read(ref reader, elementType, Options); + dictionaryElementValue[state.Current.JsonPropertyNameAsString!] = value; } else { // Avoid a type reference to JsonObject and its converter to support trimming. Debug.Assert(propValue is Nodes.JsonObject); - ConverterBase.ReadElementAndSetProperty(propValue, state.Current.JsonPropertyNameAsString!, ref reader, Options, ref state); } return true; + + JsonConverter GetDictionaryValueConverter(Type dictionaryValueType) + { + JsonConverter converter; + JsonTypeInfo? dictionaryValueInfo = RuntimeTypeInfo.ElementTypeInfo; + if (dictionaryValueInfo != null) + { + // Fast path when there is a generic type such as Dictionary<,>. + converter = dictionaryValueInfo.PropertyInfoForTypeInfo.ConverterBase; + } + else + { + // Slower path for non-generic types that implement IDictionary<,>. + // It is possible to cache this converter on JsonTypeInfo if we assume the property value + // will always be the same type for all instances. + converter = Options.GetConverterInternal(dictionaryValueType); + } + + Debug.Assert(converter != null); + return converter; + } } internal abstract bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref Utf8JsonReader reader); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs index f7e0243a5492c8..853ec365189827 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs @@ -1239,7 +1239,7 @@ public static void CustomJsonElementConverterInExtensionProperty() ClassWithExtensionPropertyAsJsonElement obj = JsonSerializer.Deserialize(Json, options); JsonElement overflowProp = obj.MyOverflow["hello"]; - Assert.Equal(JsonValueKind.String, overflowProp.ValueKind); + Assert.Equal(JsonValueKind.Undefined, overflowProp.ValueKind); string newJson = JsonSerializer.Serialize(obj, options); Assert.Equal("{\"hello\":{\"Hi\":\"There\"}}", newJson); From 3495ce9b5a3835bc456c9285d81ea1b6aac812df Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Thu, 13 May 2021 13:32:25 -0500 Subject: [PATCH 3/3] Fix nullable issue --- .../System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 732cff7b0ee61f..2a97240d67b976 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -378,7 +378,7 @@ internal bool ReadJsonAndAddExtensionProperty( else { JsonConverter converter = (JsonConverter)GetDictionaryValueConverter(JsonTypeInfo.ObjectType); - object value = converter.Read(ref reader, JsonTypeInfo.ObjectType, Options); + object value = converter.Read(ref reader, JsonTypeInfo.ObjectType, Options)!; dictionaryObjectValue[state.Current.JsonPropertyNameAsString!] = value; } }