2017-01-26 3 views
2

HashSet<string>JsonConvert.SerializeObjectです。配列にシリアライズします。Newtonsoft.Json.JsonConvertのコンターをHashSet/Dictionaryに使用するように設定します。

JsonConvert.DeserializeObject<HashSet<string>>を使用してデシリアライズすると、同じ値の新しいHashSet<string>が得られます。ただし、Comparerはリセットされています。

// 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を使用するためです。

代わりにStringComparer.OrdinalIgnoreCaseを使用するように指示するにはどうすればよいですか?

シリアル化されたデータにHashSet<string>.Comparerプロパティを含めることは望ましくありません(JSONでは単純な配列にする必要があります)、デシリアライズの時点で指定します。

ハッシュセットはルートオブジェクトであるときには、代わりに JsonConvert.PopulateObject()を使用することができ

答えて

2

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

ハッシュセットはないルートオブジェクトである場合には事前に割り当てられた場合ObjectCreationHandling.Replaceが有効になっていない限り、Json.NETがそれを移植します。あるいは、

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

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

あなたがCustomCreationConverter<HashSet<T>>をサブクラス化し、コンバータのCreate()メソッド内で必要とされた比較で設定したハッシュ割り当てることができます::

をこれが含むタイプが必要な比較演算子で設定したハッシュ、例えばを事前に割り当てることができます
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)); 
+1

乾杯(+1とANS)御馳走を働きました!私の質問の例は単純化され、 'HashSet'は本当にプロパティです。私はそれを以下のように変更しました: 'public HashSet PropName {get;セット; } =新しいHashSet (StringComparer.OrdinalIgnoreCase);そしてそれはうまくいった。 – Keith

+0

@Keith - サブクラス化する 'CustomCreationConverter 'もオプションです。しかし、私は、コンストラクタでハッシュセットを事前に割り当てるといいと思います。 – dbc

関連する問題