2011-09-27 63 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中的中间集合。

相关问题