2012-11-01 21 views
10

Bối cảnh: Tôi cần truyền một đối tượng có chứa một số lượng lớn các thuộc tính/trường (đến Lớp giao diện người dùng từ Tầng giữa). Trong danh sách các thuộc tính này, một là kiểu Version không được deserialized một cách chính xác từ định dạng chuỗi JSON. Tôi có một định dạng JSON được chọn trên XML khi JSON tuần tự hóa thành chuỗi sẽ trả về kết quả chuỗi ngắn.Tại sao System.Version trong chuỗi JSON không deserialize một cách chính xác?

Sự cố: System.Version không được deserialized chính xác. Tôi đã thử hai Thư viện .NET khác nhau. Sau đây là các đoạn mã cho mỗi:

Code Snippet 1 sử dụng ServiceStack .NET library:

 var version = new Version(1, 2, 3, 0); 
     string reportJSON = JsonSerializer.SerializeToString<Version>(version); 
     //{"Major":1,"Minor":2,"Build":3,"Revision":0,"MajorRevision":0,"MinorRevision":0} 


     Version report2 = JsonSerializer.DeserializeFromString<Version>(reportJSON); 
     string reportJSON2 = JsonSerializer.SerializeToString<Version>(report2); 
     //{"Major":0,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1} 

Code Snippet 2 sử dụng Newtonsoft .NET library nhưng với kết quả tương tự:

 var version = new Version(1, 2, 3, 0); 
     string reportJSON = JsonConvert.SerializeObject(version); 
     //{"Major":1,"Minor":2,"Build":3,"Revision":0,"MajorRevision":0,"MinorRevision":0} 


     Version report2 = JsonConvert.DeserializeObject<Version>(reportJSON); 
     string reportJSON2 = JsonConvert.SerializeObject(report2); 
     //{"Major":0,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1} 

Làm thế nào để sửa lỗi này? Hoặc thư viện JSON.NET nào khác có thể hoạt động chính xác?

+0

có thể trùng lặp của [Tôi có thể deserialize cho một đối tượng bất biến bằng cách sử dụng JavascriptSerializer?] (Http://stackoverflow.com/questions/4080644/can-i-deserialize-to-an-immutable-object-using-javascriptserializer) – spender

+0

@ spender: nhưng nó hoạt động tốt với các đối tượng chuỗi không thay đổi được. – Monish

+1

@Monish [Here] (http://stackoverflow.com/a/2085890/1180426) là một liên kết giải thích tại sao lớp 'Version' không có khả năng tuần tự hóa XML, nhưng tôi khá chắc chắn cơ chế tương tự áp dụng cho các trình tuần tự hóa JSON . –

Trả lời

6

Thuộc tính của lớp Version không có setter. Chúng chỉ trả về giá trị của các trường riêng tương ứng của chúng. Do đó, deserializer không thể thay đổi giá trị của chúng.

Nhưng với Json.NET bạn có thể viết một lớp chuyển đổi tùy chỉnh xử lý việc deserialization của lớp Version.

Hãy coi chừng: Mã này chưa được thử nghiệm rất tốt ...

public class VersionConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     // default serialization 
     serializer.Serialize(writer, value); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // create a new Version instance and pass the properties to the constructor 
     // (you may also use dynamics if you like) 
     var dict = serializer.Deserialize<Dictionary<string, int>>(reader); 
     return new Version(dict["Major"], dict["Minor"], dict["Build"], dict["Revision"]); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Version); 
    } 
} 

Sau đó, bạn phải xác định rằng bạn muốn sử dụng bộ chuyển đổi:

var v = new Version(1, 2, 3, 4); 
string json = JsonConvert.SerializeObject(v); 

var v2 = JsonConvert.DeserializeObject<Version>(json, new VersionConverter()); 

Json.NET quyết định cho dù sử dụng một trong các trình chuyển đổi bạn đã chỉ định. Vì vậy, bạn luôn có thể chỉ định trình chuyển đổi, như được hiển thị bên dưới. Json.NET sẽ sử dụng một trong các trình biến đổi của bạn nếu chúng khớp với một loại trong phạm vi SomeClass.

var result = JsonConvert.DeserializeObject<SomeClass>(json, new VersionConverter()); 
12

Thư viện Newtonsoft.Json cung cấp một bộ chuyển đổi phổ biến trong không gian tên Newtonsoft.Json.Converters, bao gồm một VersionConverter bạn có thể sử dụng để serialize và deserialize System.Version.

Lưu ý rằng bạn phải sử dụng VersionConverter cả cho serialization và deserialization, mặc dù.
Đó là do việc tuần tự hóa tiêu chuẩn sẽ tạo ra ví dụ: {"Major":1,"Minor":2,"Build":3,"Revision":0,"MajorRevision":0,"MinorRevision":0} trong khi VersionConverter deserialization mong đợi một chuỗi đơn giản như trong "1.2.3".

Vì vậy, việc sử dụng sẽ là:

using Newtonsoft.Json; 
using Newtonsoft.Json.Converters; 

string s = JsonConvert.SerializeObject(version, new VersionConverter()); 
Version v = JsonConvert.DeserializeObject<Version>(s, new VersionConverter()); 

Tôi không chắc chắn phiên bản đầu tiên của Newtonsoft.Json bao gồm chuyển đổi đó là những gì. Tôi có nó và nó là 5.0.6.

+0

Làm việc cho tôi, chỉ có tôi đã phải thực hiện một chút thay đổi kể từ khi tôi đang sử dụng chữ ký DeserializeObject được đối tượng JsonSerializerSettings: settings.Converters.Add (new VersionConverter()); (không quá tải sẽ mất cả cài đặt và bộ sưu tập bộ chuyển đổi) – Alonzzo2

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