如何使Json Serialize忽略字典键

时间:2019-10-22 10:12:23

标签: c# json dictionary serialization json.net

我正在尝试对类中的字典进行序列化,即使我将CustomAttributes参数设置为false,ProcessDictionaryKeys字典中的键也会被格式化。

我添加了[JsonProperty],如下所示:

[JsonProperty(NamingStrategyType = typeof(SnakeCaseNamingStrategy), NamingStrategyParameters = new object[] { false, false })]
public IDictionary<string, string> CustomAttributes { get; set; }

我的CustomAttributes数据如下:

CustomAttributes = new Dictionary<string, string>()
{
    {"Custom Attribute 1", "1"},
    {"CustomAttribute 2", "2"}
}

和生成的JSON如下:

custom_attributes\":{\"custom Attribute 1\":\"1\",\"customAttribute 2\":\"2\"

如您所见,每个字典键的首字母都没有大写。我该如何阻止这种情况的发生?

编辑:将ProcessDictionaryKeys参数更改为true似乎没有什么区别。

1 个答案:

答案 0 :(得分:1)

问题并不能仅用演示小提琴#1 here中所示的问题中的代码来重现。

相反,您必须使用JsonSerializerSettings.ContractResolver.NamingStrategy.ProcessDictionaryKeys = true的全局全局序列化程序设置进行序列化,例如CamelCasePropertyNamesContractResolver

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
var json = JsonConvert.SerializeObject(root, Formatting.Indented, settings);

演示小提琴#2 here

假设是正确的,[JsonProperty(NamingStrategyType = typeof(SnakeCaseNamingStrategy), NamingStrategyParameters = new object[] { false, false })]不会导致字典键逐字序列化的原因是JsonPropertyAttribute.NamingStrategyType仅适用于属性名称本身(此处为{{ 1}}),而不是属性的的属性名称。如果要对属性项应用命名策略,则需要类似CustomAttributes的东西,但是JsonPropertyAttribute没有这样的功能。

那么,您有什么选择?

  1. 您可以修改全局命名策略,以逐字序列化字典名称,如 Keep casing when serializing dictionaries 中所示。

  2. 您可以将ItemNamingStrategyType子类化,并将[JsonDictionary(NamingStrategyType = typeof(DefaultNamingStrategy))]应用于{em> this answer 中的Applying JsonDictionary attribute to dictionary

    Dictionary<TKey, TValue>

    再后来:

    [JsonDictionary(NamingStrategyType = typeof(DefaultNamingStrategy))]
    public class VerbatimDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
    }
    

    演示小提琴#3 here

  3. 您可以引入一个custom JsonConverter,该序列使用默认的命名策略对CustomAttributes = new VerbatimDictionary<string, string>() { {"Custom Attribute 1", "1"}, {"CustomAttribute 2", "2"} } 进行序列化。首先,定义以下转换器:

    IDictionary<TKey, TValue>

    并按如下所示应用它:

    public class VerbatimDictionaryConverter<TKey, TValue> : JsonConverter<IDictionary<TKey, TValue>>
    {
        [JsonDictionary(NamingStrategyType = typeof(DefaultNamingStrategy))]
        class VerbatimDictionarySerializationSurrogate : IReadOnlyDictionary<TKey, TValue>
        {
            readonly IDictionary<TKey, TValue> dictionary;
    
            public VerbatimDictionarySerializationSurrogate(IDictionary<TKey, TValue> dictionary) 
            { 
                if (dictionary == null) 
                    throw new ArgumentNullException(nameof(dictionary));
                this.dictionary = dictionary; 
            }
            public bool ContainsKey(TKey key) { return dictionary.ContainsKey(key); }
            public bool TryGetValue(TKey key, out TValue value) { return dictionary.TryGetValue(key, out value); }
            public TValue this[TKey key] { get { return dictionary[key]; } }
            public IEnumerable<TKey> Keys { get { return dictionary.Keys; } }
            public IEnumerable<TValue> Values { get { return dictionary.Values; } }
            public int Count { get { return dictionary.Count; } }
            public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return dictionary.GetEnumerator(); }
            IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
        }
    
        public override void WriteJson(JsonWriter writer, IDictionary<TKey, TValue> value, JsonSerializer serializer)
        {
            serializer.Serialize(writer, new VerbatimDictionarySerializationSurrogate(value));
        }
    
        public override bool CanRead { get { return false; } }
    
        public override IDictionary<TKey, TValue> ReadJson(JsonReader reader, Type objectType, IDictionary<TKey, TValue> existingValue, bool hasExistingValue, JsonSerializer serializer) { throw new NotImplementedException(); }
    }
    

    演示小提琴#4 here