How to make Json Serialize ignore dictionary keys

五迷三道 提交于 2020-12-26 08:22:54

问题


I'm trying to serialize a dictionary within a class and the keys inside the CustomAttributes dictionary are getting formatted even though I've provided the ProcessDictionaryKeys parameter as false.

I've added [JsonProperty] as shown below:

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

my CustomAttributes data looks like this:

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

and the JSON which is produced looks like:

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

As you can see, the first letter of each of the dictionary keys are being uncapitalised. How can I stop this from happening?

EDIT: Changing the ProcessDictionaryKeys parameter to true doesn't seem to make any difference.


回答1:


The problem doesn't reproduce with just the code in your question as shown in demo fiddle #1 here.

Instead, you must be serializing with some global serializer settings for which JsonSerializerSettings.ContractResolver.NamingStrategy.ProcessDictionaryKeys = true such as CamelCasePropertyNamesContractResolver:

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

Demo fiddle #2 here.

Assuming that's correct, the reason that [JsonProperty(NamingStrategyType = typeof(SnakeCaseNamingStrategy), NamingStrategyParameters = new object[] { false, false })] does not cause the dictionary keys to be serialized verbatim is that JsonPropertyAttribute.NamingStrategyType only applies to the property name itself (here CustomAttributes) not the property names of property's items. If you wanted to apply a naming strategy to the property's items you would need something like ItemNamingStrategyType -- but JsonPropertyAttribute has no such functionality.

So, what are your options?

  1. You could modify your global naming strategy to serialize dictionary names verbatim as shown in Keep casing when serializing dictionaries.

  2. You could subclass Dictionary<TKey, TValue> and apply [JsonDictionary(NamingStrategyType = typeof(DefaultNamingStrategy))] to it as shown in this answer to Applying JsonDictionary attribute to dictionary:

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

    And then later:

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

    Demo fiddle #3 here.

  3. You could introduce a custom JsonConverter that serializes an IDictionary<TKey, TValue> with the default naming strategy. First, define the following converter:

    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(); }
    }
    

    And apply it as follows:

    [JsonConverter(typeof(VerbatimDictionaryConverter<string, string>))]
    public IDictionary<string, string> CustomAttributes { get; set; }       
    

    Demo fiddle #4 here.



来源:https://stackoverflow.com/questions/58501943/how-to-make-json-serialize-ignore-dictionary-keys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!