设置Newtonsoft.Json.JsonConvert的比较器以用于HashSet/Dictionary [英] Set the comparer for Newtonsoft.Json.JsonConvert to use for HashSet/Dictionary

查看:93
本文介绍了设置Newtonsoft.Json.JsonConvert的比较器以用于HashSet/Dictionary的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个HashSet<string>,它将JsonConvert.SerializeObject序列化为一个数组.

I have a HashSet<string> that JsonConvert.SerializeObject serialises to an array.

当我使用JsonConvert.DeserializeObject<HashSet<string>>反序列化时,会得到一个具有相同值的新HashSet<string>.但是,Comparer已被重置.

When I deserialise using JsonConvert.DeserializeObject<HashSet<string>> I get a new HashSet<string> with the same values. However, the Comparer has been reset.

// JSON settings
var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

// Create a case insensitive hashset
var h = new HashSet<string>(new string[] {"A", "b"}, StringComparer.OrdinalIgnoreCase);
h.Contains("a"); // TRUE

// Serialise and deserialise with Newtonsoft.Json
string s = JsonConvert.SerializeObject(h, settings);
// s = ["A", "b"]
var newH = JsonConvert.DeserializeObject<HashSet<string>>(s, settings);

// Result is now case-sensitive
newH.Contains("a"); // FALSE
newH.Contains("A"); // TRUE

这是因为JsonConvert使用区分大小写的EqualityComparer<string>.Default.

This is because JsonConvert uses EqualityComparer<string>.Default, which is case sensitive.

我如何告诉它改用StringComparer.OrdinalIgnoreCase?

我不想在序列化数据中包含HashSet<string>.Comparer属性(我认为它应该是JSON中的一个简单数组),我想在反序列化时指定它.

I don't want to include the HashSet<string>.Comparer property in the serialised data (I think it should be a simple array in JSON), I want to specify it at the point of deserialisation.

推荐答案

您可以使用

You could use JsonConvert.PopulateObject() instead, when the hash set is the root object:

var newH = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
JsonConvert.PopulateObject(s, newH);

如果哈希集不是根对象,则Json.NET将对其进行预分配,除非

When the hash set is not the root object, Json.NET will populate it if preallocated unless ObjectCreationHandling.Replace is enabled. This allows the containing type to pre-allocate the hash set with the required comparer, e.g.:

public class RootObject
{
    public RootObject() { this.Collection = new HashSet<string>(StringComparer.OrdinalIgnoreCase); }

    public HashSet<string> Collection { get; private set; }
}

或者,您可以子类化 CustomCreationConverter<HashSet<T>> 并分配在转换器的 Create() 方法中使用所需比较器设置的哈希值:

Alternatively, you could subclass CustomCreationConverter<HashSet<T>> and allocate the hash set with the required comparer within the converter's Create() method:

public class HashSetCreationConverter<T> : CustomCreationConverter<HashSet<T>>
{
    public IEqualityComparer<T> Comparer { get; private set; }

    public HashSetCreationConverter(IEqualityComparer<T> comparer)
    {
        this.Comparer = comparer;
    }

    public override HashSet<T> Create(Type objectType)
    {
        return new HashSet<T>(Comparer);
    }
}

然后执行:

var newH = JsonConvert.DeserializeObject<HashSet<string>>(s, new HashSetCreationConverter<string>(StringComparer.OrdinalIgnoreCase));

这篇关于设置Newtonsoft.Json.JsonConvert的比较器以用于HashSet/Dictionary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆