2011-09-27 59 views
11

我有一個實現IEnumerable的集合類,我無法反序列化同一個序列化版本。我使用Json.net v 4.0.2.13623Json.net序列化實現IEnumerable的自定義集合<T>

這裏是我的集合類的simplier版本,說明我的問題

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

當我序列化,我得到下面的JSON

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

但是當我嘗試反序列化時,我得到以下異常 System.Exception:無法創建並填充列表類型MyTypes

還有t使用裏德序列化的提示,但沒有成功

這些測試功能我用

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

您應該序列化並反序列化爲具體集合,例如List 而不是IEnumerable 。爲了對某些東西進行反序列化,它需要一個實現而不僅僅是一個接口。 – Deleted

+0

Chris,改變了子類ReadOnlyCollection 與其他一些變化,但我可以知道反序列化集合 – pmcgrath

+1

其實你也可以使用IList 。它會爲你創建一個列表。但是沒有爲IEnumerable 定義默認集合。 – Mithon

回答

2

我相信JSON .NET取決於有它反序列化的類型參數的構造函數。從反序列化的角度來看,它不知道該向constrcut提供什麼。

至於你的收藏,又是它應該怎麼知道如何填充的IEnumerable<T>的實現只定義瞭如何枚舉集合而不是如何填充它。你應該直接反序列化一些標準的IEnumerable<MyType>(或直接到IEnumerable<MyType>,我相信JSON.NET支持),然後將它傳遞給你的構造函數。

我相信所有的以下的應在這種情況下工作:

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

另外,雖然更多的工作,如果你需要直接反序列化可以實現在您的收藏類似的IList應該允許JSON.NET使用IList方法來填充您的集合。

+0

由於這個答案,庫已經擴展了它的能力 - 它將使用無參數的構造函數(因爲它總是有),但它也將支持創建一個實例,它通過構造函數接收所有數據,並支持具有一個IEnumerable構造函數(作爲@dbc提及的答案)。 –

2

從Json.NET 6.0 Release 3及更高版本(我在8.0.3上測試)開始,只要執行IEnumerable<MyType>的自定義類的構造函數的輸入參數爲IEnumerable<MyType>,就會自動運行。從release notes

要一成不變的.NET集合所有未來的創造者:如果你的T收集有一個構造函數的IEnumerable然後反序列化到您的收藏時Json.NET會自動工作,否則你全力以赴的運氣。

由於MyTypes類的問題有這樣一個構造函數,這個現在只是工作。示範小提琴:https://dotnetfiddle.net/LRJHbd

如果沒有這樣的構造函數,則需要添加無參數的構造函數,並使用Add(MyType item)方法實現ICollection<MyType>(而不僅僅是IEnumerable<MyType>)。然後Json.NET可以構造並填充集合。或者反序列化爲original answer中的中間集合。

相關問題