c# - 如何让 Json Serialize 忽略字典键

标签 c# json dictionary serialization json.net

我正在尝试序列化一个类中的字典,并且 CustomAttributes 字典中的键正在格式化,即使我提供的 ProcessDictionaryKeys 参数为 false。

我添加了 [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 似乎没有任何区别。

最佳答案

如 demo fiddle #1 here 所示,仅使用问题中的代码不会重现问题。 .

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

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

演示 fiddle #2 here .

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

那么,您有哪些选择?

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

  2. 你可以继承Dictionary<TKey, TValue>并申请 [JsonDictionary(NamingStrategyType = typeof(DefaultNamingStrategy))] this answer 所示给 Applying JsonDictionary attribute to dictionary :

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

    然后:

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

    演示 fiddle #3 here .

  3. 你可以介绍一个 custom JsonConverter 序列化 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(); }
    }
    

    并按如下方式应用:

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

    演示 fiddle #4 here .

关于c# - 如何让 Json Serialize 忽略字典键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58501943/

相关文章:

c# - 'deaden' 可能是一个asp.net超链接吗?

c# - 为什么忽略 STAThread 属性?

c++ - 'erase' ing 之后的映射迭代器行为

c# - 将应用程序部署到 IIS(MVC3、EF 4.3)后分页出现意外结果

c# - 从数据表添加到字典记录

python - 在 Python 中过滤 json 字符串的最快方法

json - 使用 node.js 循环 JSON

javascript - 如何将 JSON 字符串对象值转换为整数?

dictionary - Data.Map - 为什么有 `takeWhileAntitone` 但没有 `takeWhile`?

java - 根据 Map 内 TreeSet 中的值范围返回键