如何使 Json 序列化忽略字典键



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

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

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

我的自定义属性数据如下所示:

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 所示。

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

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

演示小提琴#2在这里。

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

那么,您有什么选择?

  1. 您可以修改全局命名策略以逐字序列化字典名称,如序列化字典时保持大小写所示。

  2. 您可以子类化Dictionary<TKey, TValue>并对其应用[JsonDictionary(NamingStrategyType = typeof(DefaultNamingStrategy))],如将 JsonDictionary 属性应用于字典的回答所示:

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

    然后后来:

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

    演示小提琴#3在这里。

  3. 您可以引入一个自定义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; }       
    

    演示小提琴#4在这里。

最新更新