From d9dd0dac4285368002740333d6772d4db79d82c1 Mon Sep 17 00:00:00 2001 From: marcnet80 <46241368+marcnet80@users.noreply.github.com> Date: Thu, 14 Nov 2019 02:49:54 +0200 Subject: [PATCH] =?UTF-8?q?DictionaryKeyPolicy=20not=20applied=20to=20keys?= =?UTF-8?q?=20that=20contain=20non=20primitive=20ty=E2=80=A6=20(#41691)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * DictionaryKeyPolicy not applied to keys that contain non primitive types #41176 https://github.com/dotnet/corefx/issues/41176#event-2697607085 * #41176: DictionaryKeyPolicy not applied to keys that contain non primitive types https://github.com/dotnet/corefx/issues/41176 * add unit tests https://github.com/dotnet/corefx/pull/41691 * Remove check for JsonExtensionDataAttribute to avoid reflection. --- .../JsonSerializer.Write.HandleDictionary.cs | 6 + .../DictionaryTests.KeyPolicy.cs | 142 ++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs b/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs index d39ea99a9873..22c1f2324cee 100644 --- a/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs +++ b/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs @@ -81,8 +81,14 @@ public static partial class JsonSerializer jsonPropertyInfo.GetDictionaryKeyAndValue(ref state.Current, out key, out value); } + if (options.DictionaryKeyPolicy != null && state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) + { + key = options.DictionaryKeyPolicy.ConvertName(key); + } + // An object or another enumerator requires a new stack frame. state.Push(elementClassInfo, value); + state.Current.KeyName = key; } diff --git a/src/System.Text.Json/tests/Serialization/DictionaryTests.KeyPolicy.cs b/src/System.Text.Json/tests/Serialization/DictionaryTests.KeyPolicy.cs index 47f1595cc2a5..05c7cbe5a1a4 100644 --- a/src/System.Text.Json/tests/Serialization/DictionaryTests.KeyPolicy.cs +++ b/src/System.Text.Json/tests/Serialization/DictionaryTests.KeyPolicy.cs @@ -258,5 +258,147 @@ public static void KeyConflict_Serialize_WriteAll() // Check that we write all. Assert.Equal(@"{""myInt"":1,""myInt"":2}", json); } + + [Fact] + public static void CamelCaseSerialize_ApplyDictionaryKeyPolicy() + { + const string JsonCamel = @"{""keyDict"":{""keyString"":""text"",""keyNumber"":1000,""keyBool"":true},""keyList"":[1,2,3]}"; + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }; + + var obj = new Dictionary(); + obj["KeyDict"] = new Dictionary() + { + { "KeyString", "text" }, + { "KeyNumber", 1000 }, + { "KeyBool", true } + }; + obj["KeyList"] = new List() { 1, 2, 3 }; + + var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }); + + Assert.Equal(JsonCamel, json); + } + + [Fact] + public static void SerializationWithJsonExtensionDataAttribute_IgoneDictionaryKeyPolicy() + { + var expectedJson = @"{""KeyInt"":1000,""KeyString"":""text"",""KeyBool"":true,""KeyObject"":{},""KeyList"":[],""KeyDictionary"":{}}"; + var obj = new ClassWithExtensionDataProperty(); + obj.Data = new Dictionary() + { + { "KeyInt", 1000 }, + { "KeyString", "text" }, + { "KeyBool", true }, + { "KeyObject", new object() }, + { "KeyList", new List() }, + { "KeyDictionary", new Dictionary() } + }; + string json = JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }); + Assert.Equal(expectedJson, json); + } + + private class ClassWithExtensionDataProperty + { + [JsonExtensionData] + public Dictionary Data { get; set; } + } + + [Fact] + public static void CamelCaseSerialize_ForTypedDictionary_ApplyDictionaryKeyPolicy() + { + const string JsonCamel = @"{""keyDict"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}"; + var obj = new Dictionary() + { + { "KeyDict", CreateCustomObject() } + }; + var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }); + + Assert.Equal(JsonCamel, json); + } + + private class CustomClass + { + public string Name { get; set; } + public int Number { get; set; } + public bool isValid { get; set; } + public List Values { get; set; } + } + + private static CustomClass CreateCustomObject() + { + return new CustomClass { Name = "text", Number = 1000, isValid = true, Values = new List() { 1, 2, 3 } }; + } + + [Fact] + public static void CamelCaseSerialize_ForNestedTypedDictionary_ApplyDictionaryKeyPolicy() + { + const string JsonCamel = @"{""keyDict"":{""nestedKeyDict"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}}"; + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }; + var obj = new Dictionary>(){ + { "KeyDict", new Dictionary() + {{ "NestedKeyDict", CreateCustomObject() }} + }}; + var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }); + + Assert.Equal(JsonCamel, json); + } + + private class TestClassWithDictionary + { + public Dictionary Data { get; set; } + } + + [Fact] + public static void CamelCaseSerialize_ForClassWithDictionaryProperty_ApplyDictionaryKeyPolicy() + { + const string JsonCamel = @"{""Data"":{""keyObj"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}}"; + var obj = new TestClassWithDictionary(); + obj.Data = new Dictionary { + {"KeyObj", CreateCustomObject() } + }; + var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }); + Assert.Equal(JsonCamel, json); + } + + [Fact] + public static void CamelCaseSerialize_ForKeyValuePairWithDictionaryValue_ApplyDictionaryKeyPolicy() + { + const string JsonCamel = @"{""Key"":""KeyPair"",""Value"":{""keyDict"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}}"; + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }; + var obj = new KeyValuePair> + ("KeyPair", new Dictionary { + {"KeyDict", CreateCustomObject() } + }); + var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }); + + Assert.Equal(JsonCamel, json); + } } }