Make CreateConverter public and add options (dotnet/corefx#39438)
authorJeremy Kuhne <jkuhne@microsoft.com>
Mon, 15 Jul 2019 19:42:55 +0000 (12:42 -0700)
committerGitHub <noreply@github.com>
Mon, 15 Jul 2019 19:42:55 +0000 (12:42 -0700)
* Make CreateConverter public and add options

This is to facilitate composition with factory converters.

* Remove unnecessary using

Commit migrated from https://github.com/dotnet/corefx/commit/db543576d757f2d448f004f5e9ba2b77c2b497fe

src/libraries/System.Text.Json/ref/System.Text.Json.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonConverterEnum.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonKeyValuePairConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs
src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.BadConverters.cs
src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.List.cs
src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.cs
src/libraries/System.Text.Json/tests/Serialization/EnumConverterTests.cs

index ee3663c..82bc52d 100644 (file)
@@ -467,7 +467,7 @@ namespace System.Text.Json.Serialization
     public abstract partial class JsonConverterFactory : System.Text.Json.Serialization.JsonConverter
     {
         protected internal JsonConverterFactory() { }
-        protected abstract System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert);
+        public abstract System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options);
     }
     public abstract partial class JsonConverter<T> : System.Text.Json.Serialization.JsonConverter
     {
@@ -497,6 +497,6 @@ namespace System.Text.Json.Serialization
         public JsonStringEnumConverter() { }
         public JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true) { }
         public override bool CanConvert(System.Type typeToConvert) { throw null; }
-        protected override System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert) { throw null; }
+        public override System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; }
     }
 }
index aada8d1..7cdada1 100644 (file)
@@ -17,7 +17,7 @@ namespace System.Text.Json.Serialization.Converters
             return type.IsEnum;
         }
 
-        protected override JsonConverter CreateConverter(Type type)
+        public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
         {
             JsonConverter converter = (JsonConverter)Activator.CreateInstance(
                 typeof(JsonConverterEnum<>).MakeGenericType(type),
index 833bb0a..90d3128 100644 (file)
@@ -18,7 +18,7 @@ namespace System.Text.Json.Serialization.Converters
             return (generic == typeof(KeyValuePair<,>));
         }
 
-        protected override JsonConverter CreateConverter(Type type)
+        public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
         {
             Type keyType = type.GetGenericArguments()[0];
             Type valueType = type.GetGenericArguments()[1];
index a4585fc..5e4d686 100644 (file)
@@ -19,19 +19,20 @@ namespace System.Text.Json.Serialization
         /// </summary>
         protected internal JsonConverterFactory() { }
 
-        internal JsonConverter GetConverterInternal(Type typeToConvert)
+        internal JsonConverter GetConverterInternal(Type typeToConvert, JsonSerializerOptions options)
         {
             Debug.Assert(CanConvert(typeToConvert));
-            return CreateConverter(typeToConvert);
+            return CreateConverter(typeToConvert, options);
         }
 
         /// <summary>
         /// Create a converter for the provided <see cref="Type"/>.
         /// </summary>
-        /// <param name="typeToConvert">The type to convert.</param>
+        /// <param name="typeToConvert">The <see cref="Type"/> being converted.</param>
+        /// <param name="options">The <see cref="JsonSerializerOptions"/> being used.</param>
         /// <returns>
         /// An instance of a <see cref="JsonConverter{T}"/> where T is compatible with <paramref name="typeToConvert"/>.
-        /// </returns>        
-        protected abstract JsonConverter CreateConverter(Type typeToConvert);
+        /// </returns>
+        public abstract JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options);
     }
 }
index 6152dc8..12980ec 100644 (file)
@@ -88,7 +88,7 @@ namespace System.Text.Json
 
             if (converter is JsonConverterFactory factory)
             {
-                converter = factory.GetConverterInternal(runtimePropertyType);
+                converter = factory.GetConverterInternal(runtimePropertyType, this);
             }
 
             return converter;
@@ -154,7 +154,7 @@ namespace System.Text.Json
             // Allow redirection for generic types or the enum converter.
             if (converter is JsonConverterFactory factory)
             {
-                converter = factory.GetConverterInternal(typeToConvert);
+                converter = factory.GetConverterInternal(typeToConvert, this);
                 if (converter == null || converter.TypeToConvert == null)
                 {
                     throw new ArgumentNullException("typeToConvert");
index aeaa8f6..2cbd3a1 100644 (file)
@@ -53,7 +53,7 @@ namespace System.Text.Json.Serialization
         }
 
         /// <inheritdoc />
-        protected override JsonConverter CreateConverter(Type typeToConvert)
+        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
         {
             JsonConverter converter = (JsonConverter)Activator.CreateInstance(
                 typeof(JsonConverterEnum<>).MakeGenericType(typeToConvert),
index a6aed82..3740241 100644 (file)
@@ -87,7 +87,7 @@ namespace System.Text.Json.Serialization.Tests
                 return true;
             }
 
-            protected override JsonConverter CreateConverter(Type typeToConvert)
+            public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
             {
                 return null;
             }
index 35ea08d..4ff3b0d 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Text.Json.Serialization.Tests
                     arg == typeof(long);
             }
 
-            protected override JsonConverter CreateConverter(Type type)
+            public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
             {
                 Type elementType = type.GetGenericArguments()[0];
 
index c277a79..cb0fb03 100644 (file)
@@ -31,5 +31,39 @@ namespace System.Text.Json.Serialization.Tests
             string jsonElementString = jsonElement.ToString();
             Assert.Equal(expectedJson, jsonElementString);
         }
+
+        [Fact]
+        public static void OptionsArePassedToCreateConverter()
+        {
+            TestFactory factory = new TestFactory();
+            JsonSerializerOptions options = new JsonSerializerOptions { Converters = { factory } };
+            string json = JsonSerializer.Serialize("Test", options);
+            Assert.Equal(@"""Test""", json);
+            Assert.Same(options, factory.Options);
+        }
+
+        public class TestFactory : JsonConverterFactory
+        {
+            public JsonSerializerOptions Options { get; private set; }
+
+            public override bool CanConvert(Type typeToConvert) => true;
+
+            public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
+            {
+                Options = options;
+                return new SimpleConverter();
+            }
+
+            public class SimpleConverter : JsonConverter<string>
+            {
+                public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+                {
+                    throw new NotImplementedException();
+                }
+
+                public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+                    => writer.WriteStringValue(value);
+            }
+        }
     }
 }
index bd6c6d2..17447fd 100644 (file)
@@ -144,5 +144,26 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(DayOfWeek.Friday, week.WorkEnd);
             Assert.Equal(DayOfWeek.Saturday, week.WeekEnd);
         }
+
+        [Fact]
+        public void EnumConverterComposition()
+        {
+            JsonSerializerOptions options = new JsonSerializerOptions { Converters = { new NoFlagsStringEnumConverter() } };
+            string json = JsonSerializer.Serialize(DayOfWeek.Monday, options);
+            Assert.Equal(@"""Monday""", json);
+            json = JsonSerializer.Serialize(FileAccess.Read);
+            Assert.Equal(@"1", json);
+        }
+
+        public class NoFlagsStringEnumConverter : JsonConverterFactory
+        {
+            private static JsonStringEnumConverter s_stringEnumConverter = new JsonStringEnumConverter();
+
+            public override bool CanConvert(Type typeToConvert)
+                => typeToConvert.IsEnum && !typeToConvert.IsDefined(typeof(FlagsAttribute), inherit: false);
+
+            public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
+                => s_stringEnumConverter.CreateConverter(typeToConvert, options);
+        }
     }
 }