首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Json.NET Dictionary<string,使用StringComparer序列化的T>

Json.NET Dictionary<string,使用StringComparer序列化的T>
EN

Stack Overflow用户
提问于 2014-01-08 00:06:45
回答 3查看 4.7K关注 0票数 20

我有一本字典Dictionary<string, Dictionary<string, object>>。外部字典和内部字典都有一个相等比较器集(在我的例子中是StringComparer.OrdinalIgnoreCase)。在对字典进行序列化和反序列化之后,两个字典的比较器都没有设置为StringComparer.OrdinalIgnoreCase

如果您可以在代码中控制字典的创建,则可以创建一个从字典继承的类,并在该类的默认构造函数中设置比较器。但是,如果您无法控制字典的创建,而是从其他代码中获取字典,该怎么办?

有没有办法用比较器正确地序列化/反序列化它?

EN

回答 3

Stack Overflow用户

发布于 2014-01-08 00:36:57

一个简单的想法是创建一个Dictionary<string, string>的子类,在默认情况下将比较器设置为StringComparer.OrdinalIgnoreCase,然后反序列化到它而不是普通字典中。例如:

代码语言:javascript
复制
class CaseInsensitiveDictionary<V> : Dictionary<string, V>
{
    public CaseInsensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase)
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""Foo"" : 
            {
                ""fiZZ"" : 1,
                ""BUzz"" : ""yo""
            },
            ""BAR"" :
            {
                ""dIt"" : 3.14,
                ""DaH"" : true
            }
        }";

        var dict = JsonConvert.DeserializeObject<CaseInsensitiveDictionary<CaseInsensitiveDictionary<object>>>(json);

        Console.WriteLine(dict["foo"]["fizz"]);
        Console.WriteLine(dict["foo"]["buzz"]);
        Console.WriteLine(dict["bar"]["dit"]);
        Console.WriteLine(dict["bar"]["dah"]);
    }
}

输出:

代码语言:javascript
复制
1
yo
3.14
True
票数 19
EN

Stack Overflow用户

发布于 2014-01-08 08:19:51

最好创建一个根据需要创建字典对象的转换器。这正是Newtonsoft.Json.Converters.CustomCreationConverter<T>设计的目的。

这里有一个可以创建需要自定义比较器的字典的实现。

代码语言:javascript
复制
public class CustomComparerDictionaryCreationConverter<T> : CustomCreationConverter<IDictionary>
{
    private IEqualityComparer<T> comparer;
    public CustomComparerDictionaryCreationConverter(IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            throw new ArgumentNullException("comparer");
        this.comparer = comparer;
    }

    public override bool CanConvert(Type objectType)
    {
        return HasCompatibleInterface(objectType)
            && HasCompatibleConstructor(objectType);
    }

    private static bool HasCompatibleInterface(Type objectType)
    {
        return objectType.GetInterfaces()
            .Where(i => HasGenericTypeDefinition(i, typeof(IDictionary<,>)))
            .Where(i => typeof(T).IsAssignableFrom(i.GetGenericArguments().First()))
            .Any();
    }

    private static bool HasGenericTypeDefinition(Type objectType, Type typeDefinition)
    {
        return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeDefinition;
    }

    private static bool HasCompatibleConstructor(Type objectType)
    {
        return objectType.GetConstructor(new Type[] { typeof(IEqualityComparer<T>) }) != null;
    }

    public override IDictionary Create(Type objectType)
    {
        return Activator.CreateInstance(objectType, comparer) as IDictionary;
    }
}

但是请注意,此转换器将应用于键与T协变的所有字典类型,而与值类型无关。

然后使用它:

代码语言:javascript
复制
var converters = new JsonConverter[]
{
    new CustomComparerDictionaryCreationConverter<string>(StringComparer.OrdinalIgnoreCase),
};
var dict = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(jsonString, converters);
票数 10
EN

Stack Overflow用户

发布于 2016-05-07 15:19:38

创建一个扩展方法,该方法将值从区分大小写的字典复制到新的不区分大小写的字典。

代码语言:javascript
复制
public static Dictionary<string, T> ToCaseInsensitive<T>(this Dictionary<string, T> caseSensitiveDictionary)
{
    var caseInsensitiveDictionary = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
    caseSensitiveDictionary.Keys.ToList()
        .ForEach(k => caseInsensitiveDictionary[k] = caseSensitiveDictionary[k]);

    return caseInsensitiveDictionary;
}

用法:

代码语言:javascript
复制
var newDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(value)
.ToCaseInsensitive();

虽然这对我来说很有效(我喜欢这个解决方案,因为它很简单),但请注意以下警告:

  • 如果字典中有重复的键(如"cat“和"CAT"),则复制
  • 会产生较小的开销,其中一个键将被覆盖。在这种情况下(如果您愿意),您可以轻松地调整该方法以抛出异常。
  • 我的解决方案在反序列化期间并不严格使用比较器,但这很可能是使字典进入不区分大小写状态的最简单方法。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20976338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档