Not all object converters return a JsonElement (#40921)
authordevsko <devsko@users.noreply.github.com>
Mon, 17 Aug 2020 19:46:24 +0000 (21:46 +0200)
committerGitHub <noreply@github.com>
Mon, 17 Aug 2020 19:46:24 +0000 (12:46 -0700)
Co-authored-by: devsko <stefan.kohlmeister@outlook.de>
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs
src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests/CustomConverterTests.cs

index 9c36014..987e897 100644 (file)
@@ -196,14 +196,13 @@ namespace System.Text.Json.Serialization
                         ref reader);
                 }
 
-                if (CanBePolymorphic && options.ReferenceHandler != null)
+                if (CanBePolymorphic && options.ReferenceHandler != null && value is JsonElement element)
                 {
                     // Edge case where we want to lookup for a reference when parsing into typeof(object)
                     // instead of return `value` as a JsonElement.
                     Debug.Assert(TypeToConvert == typeof(object));
-                    Debug.Assert(value is JsonElement);
 
-                    if (JsonSerializer.TryGetReferenceFromJsonElement(ref state, (JsonElement)(object)value, out object? referenceValue))
+                    if (JsonSerializer.TryGetReferenceFromJsonElement(ref state, element, out object? referenceValue))
                     {
                         value = (T)referenceValue;
                     }
index 77dd281..beb16ce 100644 (file)
@@ -119,5 +119,46 @@ namespace System.Text.Json.Serialization.Tests
             Customer c = JsonSerializer.Deserialize<Customer>(utf8, options);
             Assert.Null(c);
         }
+
+        public class ObjectBoolConverter : JsonConverter<object>
+        {
+            public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+            {
+                if (reader.TokenType == JsonTokenType.True)
+                {
+                    return true;
+                }
+
+                if (reader.TokenType == JsonTokenType.False)
+                {
+                    return false;
+                }
+
+                throw new JsonException();
+            }
+
+            public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        [Fact]
+        public static void VerifyObjectConverterWithPreservedReferences()
+        {
+            var json = "true";
+            byte[] utf8 = Encoding.UTF8.GetBytes(json);
+
+            var options = new JsonSerializerOptions()
+            {
+                ReferenceHandler = ReferenceHandler.Preserve,
+            };
+            options.Converters.Add(new ObjectBoolConverter());
+
+            object obj = (JsonSerializer.Deserialize<object>(utf8, options));
+
+            Assert.IsType<bool>(obj);
+            Assert.Equal(true, obj);
+        }
     }
 }