2011-09-27 9 views
11

私はIEnumerableを実装するコレクションクラスを持っており、同じもののシリアル化されたバージョンをデシリアライズするのに問題があります。私はJson.netのVここで4.0.2.13623IEnumerableを実装したカスタムコレクションのJson.netシリアル化<T>

を使用しています、私は、私は次のようなJSONを取得し、それをシリアル化するとき、私の問題

public class MyType 
{ 
    public int Number { get; private set; } 
    public MyType(int number) 
    { 
    this.Number = number; 
    } 
} 

public class MyTypes : IEnumerable<MyType> 
{ 
    private readonly Dictionary<int, MyType> c_index; 
    public MyTypes(IEnumerable<MyType> seed) 
    { 
    this.c_index = seed.ToDictionary(item => item.Number); 
    } 
    public IEnumerator<MyType> GetEnumerator() 
    { 
    return this.c_index.Values.GetEnumerator(); 
    } 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
    return this.GetEnumerator(); 
    } 
    public int CustomMethod() 
    { 
    return 1; // Just for illustration 
    } 
} 

を示して私のコレクションクラスのsimplierバージョンです

[ 
    { 
    "Number": 1 
    }, 
    { 
    "Number": 2 
    } 
] 

しかし、私はdeserializeしようとすると、私は次の例外が発生します System.Exception:リスト型のMyTypesを作成することができません

もありますリートシリアル化のヒントを使用しますが、私は

public void RoundTrip() 
{ 
    var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) }); 
    var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented); 
    var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent); 
} 
public void RoundTripWithSettings() 
{ 
    var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) }); 

    var _serializationSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Arrays }; 
    var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented, _serializationSettings); 
    var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent, _serializationSettings); 
} 

を使用していたテスト機能は誰もが自分自身のコレクションオブジェクトをシリアル化するために管理していますされているいかなる成功

これらを持っていませんでしたか?事前に

おかげ

パット

+4

IEnumerable ではなく、リストなどの具体的なコレクションにシリアル化およびデシリアライズする必要があります。デシリアライズするには、単なるインタフェースではなく実装が必要です。 – Deleted

+0

Chris、ReadOnlyCollectionをサブクラス化する他の変更を加えましたが、コレクションを逆シリアル化することができます – pmcgrath

+1

実際には、IList を使用することもできます。リストが作成されます。しかし、IEnumerable に定義されている既定のコレクションはありません。 – Mithon

答えて

2

私はJSON .NETはそれが逆シリアル化するタイプのためのパラメータなしのコンストラクタを持つに依存します信じています。デシリアライゼーションの観点からは、constrcutorに何を提供するのか分かりません。もう一度あなたのコレクションについては

は、どのようにそれだけでコレクションではないどのようにそれを移入を列挙する方法を定義IEnumerable<T>の実装を移入する方法を知ることになっています。代わりに、標準のIEnumerable<MyType>(または、私がJSON.NETがサポートしていると思われるIEnumerable<MyType>に直接)を逆シリアル化してから、コンストラクタに渡してください。

私はこのケースで動作するはずです以下のすべてを信じて:あなたは直接直列化復元する必要がある場合

var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<MyTypes[]>(_jsonContent)); 
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<List<MyTypes>>(_jsonContent)); 
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<IEnumerable<MyTypes>>(_jsonContent)); 

また、より多くの仕事が、あなたはJSON.NETを可能にしなければならないあなたのコレクションにIListのようなものを実装することができますIListメソッドを使用してコレクションを作成します。

+0

この回答から、ライブラリは機能を拡張しました。パラメータレスコンストラクタ(常にそうです)で動作しますが、すべてのデータをコンストラクタで取得するインスタンスの作成もサポートします。 IEnumerable (@dbcの言及による答えとして)をとるコンストラクタです。 –

2

IEnumerable<MyType>を実装しているカスタムクラスがIEnumerable<MyType>入力引数を取るコンストラクタを持っている限り、これはJson.NET 6.0リリース3以降(8.0.3でテスト済み)では自動的に動作します。不変.NETコレクションのすべての将来のクリエーターへ

:Tのあなたのコレクションは、そうでなければ、すべての外出、あなたのコレクションにデシリアライズするときにJson.NETが自動的に動作するのIEnumerableを取るコンストラクタを持っている場合release notesから運の

問題のMyTypesクラスは、まさにこのようなコンストラクタを持っているので、これは今だけに動作します。デモンストレーションフィドル:https://dotnetfiddle.net/LRJHbd

このようなコンストラクタがない場合は、パラメータのないコンストラクタを追加し、メソッドを使用しての代わりにICollection<MyType>を実装する必要があります。その後、Json.NETはコレクションを構築して取り込むことができます。またはoriginal answerのように中間コレクションに逆シリアル化します。

関連する問題