Json.NET Dictionary with StringComparer serialization

后端 未结 3 1866
忘掉有多难
忘掉有多难 2020-12-16 11:30

I have a dictionary Dictionary>. Both the outer dictionary and the inner one have an equality comparer set(in my

3条回答
  •  被撕碎了的回忆
    2020-12-16 12:33

    It would be better to create a converter that would create the dictionary objects as needed. This is precisely what the Newtonsoft.Json.Converters.CustomCreationConverter was designed for.

    Here's one implementation that could create dictionaries that requires custom comparers.

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

    Do note however that this converter will apply to all dictionary types where the key is covariant with T, regardless of value type.

    Then to use it:

    var converters = new JsonConverter[]
    {
        new CustomComparerDictionaryCreationConverter(StringComparer.OrdinalIgnoreCase),
    };
    var dict = JsonConvert.DeserializeObject>>(jsonString, converters);
    

提交回复
热议问题