2011-09-27 29 views
11

Tôi có một lớp sưu tập thực hiện IEnumerable và tôi đang gặp sự cố khi deserializing một phiên bản serialized của cùng. Tôi đang sử dụng Json.net v 4.0.2.13623Tuần tự hóa Json.net của bộ sưu tập tùy chỉnh thực hiện IEnumerable <T>

Đây là một phiên bản đơn giản hơn của lớp bộ sưu tập của tôi để minh họa vấn đề của tôi

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

Khi tôi serialize nó tôi nhận được json sau

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

Nhưng sau đó khi tôi cố gắng deserialize tôi nhận được ngoại lệ sau System.Exception: Không thể tạo và điền loại danh sách MyTypes

cũng có t Ried sử dụng gợi ý serialization nhưng đã không thành công

Đây là những chức năng kiểm tra tôi đã sử dụng

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

Có ai quản lý để serialize đối tượng bộ sưu tập của riêng mình?

Cảm ơn trước

Pat

+4

Bạn nên nối tiếp và deserialise vào bộ sưu tập cụ thể như Danh sách thay vì IEnumerable . Để deserialise một cái gì đó, nó cần một thực hiện hơn là chỉ là một giao diện. – Deleted

+0

Chris, Thay đổi thành phân lớp ReadOnlyCollection với một số thay đổi khác nhưng tôi có thể biết deserialize bộ sưu tập – pmcgrath

+1

Thực ra bạn cũng có thể sử dụng IList . Nó sẽ tạo một Danh sách cho bạn. Nhưng không có bộ sưu tập mặc định được xác định cho IEnumerable . – Mithon

Trả lời

2

Tôi tin JSON NET phụ thuộc vào việc có một nhà xây dựng parameterless cho các loại nó deserializes tới. Từ một quan điểm deserialization xem nó không có ý tưởng gì để cung cấp cho constrcutor.

Đối với bộ sưu tập của bạn, một lần nữa làm cách nào để biết cách triển khai thực hiện IEnumerable<T> chỉ xác định cách liệt kê bộ sưu tập không phải cách điền. Thay vào đó, bạn nên deserialize trực tiếp đến một số tiêu chuẩn IEnumerable<MyType> (hoặc trực tiếp đến IEnumerable<MyType> mà tôi tin rằng JSON.NET hỗ trợ) và sau đó chuyển nó cho nhà xây dựng của bạn.

Tôi tin rằng tất cả những điều sau đây nên làm việc trong trường hợp này:

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

Ngoài ra, mặc dù làm việc nhiều hơn, nếu bạn cần phải deserialized trực tiếp bạn có thể thực hiện một cái gì đó giống như IList trên bộ sưu tập của bạn mà nên cho phép JSON.NET để sử dụng các phương pháp IList để điền vào bộ sưu tập của bạn.

+0

Vì câu trả lời này, thư viện đã mở rộng khả năng của nó - nó sẽ làm việc với một hàm tạo tham số (vì nó luôn có) nhưng nó cũng sẽ hỗ trợ tạo một cá thể lấy tất cả dữ liệu của nó thông qua một hàm khởi tạo và nó sẽ hỗ trợ các kiểu bộ sưu tập có một hàm tạo có một số đếm được là (như câu trả lời bằng @dbc đề cập). –

2

Kể từ Json.NET 6.0 Release 3 trở lên (tôi đã thử nghiệm trên 8.0.3), điều này sẽ tự động hoạt động miễn là lớp tùy chỉnh triển khai IEnumerable<MyType> có một hàm tạo tham số đầu vào IEnumerable<MyType>. Từ release notes:

Để tất cả người sáng tạo tương lai của bộ sưu tập NET bất biến: Nếu bộ sưu tập của bạn của T có một constructor mà mất IEnumerable sau đó Json.NET sẽ tự động làm việc khi deserializing vào bộ sưu tập của bạn, nếu không bạn đã hết của may mắn.

Vì lớp học này chỉ có một hàm tạo như vậy, bây giờ chỉ hoạt động. Trình diễn fiddle: https://dotnetfiddle.net/LRJHbd.

Thiếu trình xây dựng như vậy, người ta cần phải thêm một hàm tạo tham số và triển khai ICollection<MyType> (thay vì chỉ IEnumerable<MyType>) với phương thức Add(MyType item) đang hoạt động. Json.NET sau đó có thể xây dựng và điền vào bộ sưu tập. Hoặc deserialize vào một bộ sưu tập trung gian như trong original answer.

Các vấn đề liên quan