Json.NET Dictionary with StringComparer序列化
我有一个字典Dictionary<string, Dictionary>
。 外部字典和内部字典都有一个相等比较器集(在我的例子中是StringComparer.OrdinalIgnoreCase
)。 字典序列化和反序列化后,两个字典的比较器都未设置为StringComparer.OrdinalIgnoreCase
。
如果您可以控制代码中字典的创建,则可以创建从字典inheritance的类,并在类的默认构造函数中设置comparer。 但是,如果您无法控制字典创建并从其他代码获取字典,该怎么办?
有没有办法用比较器正确序列化/反序列化?
一个简单的想法是创建Dictionary
的子类,默认情况下将比较器设置为StringComparer.OrdinalIgnoreCase
,然后反序列化为而不是普通字典。 例如:
class CaseInsensitiveDictionary : Dictionary { 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>>(json); Console.WriteLine(dict["foo"]["fizz"]); Console.WriteLine(dict["foo"]["buzz"]); Console.WriteLine(dict["bar"]["dit"]); Console.WriteLine(dict["bar"]["dah"]); } }
输出:
1 yo 3.14 True
最好创建一个可以根据需要创建字典对象的转换器。 这正是Newtonsoft.Json.Converters.CustomCreationConverter
设计目的。
这是一个可以创建需要自定义比较器的字典的实现。
public class CustomComparerDictionaryCreationConverter : CustomCreationConverter { private IEqualityComparer comparer; public CustomComparerDictionaryCreationConverter(IEqualityComparer 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 ) }) != null; } public override IDictionary Create(Type objectType) { return Activator.CreateInstance(objectType, comparer) as IDictionary; } }
但请注意,无论值类型如何,此转换器都将应用于键与T
协变的所有字典类型。
然后使用它:
var converters = new JsonConverter[] { new CustomComparerDictionaryCreationConverter(StringComparer.OrdinalIgnoreCase), }; var dict = JsonConvert.DeserializeObject>>(jsonString, converters);
创建一个扩展方法,该方法将从区分大小写的字典中的值复制到新的不区分大小写的字典。
public static Dictionary ToCaseInsensitive(this Dictionary caseSensitiveDictionary) { var caseInsensitiveDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); caseSensitiveDictionary.Keys.ToList() .ForEach(k => caseInsensitiveDictionary[k] = caseSensitiveDictionary[k]); return caseInsensitiveDictionary; }
用法:
var newDictionary = JsonConvert.DeserializeObject>(value) .ToCaseInsensitive();
虽然这对我有用(并且由于其简单性我喜欢这个解决方案),但请注意以下警告:
上述就是C#学习教程:Json.NET Dictionary with StringComparer序列化分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1008723.html