2009-02-27 34 views
22

tôi đã có mảnh sau JSON:Deserialization vấn đề với DataContractJsonSerializer

[{ 
    "name": "numToRetrieve", 
    "value": "3", 
    "label": "Number of items to retrieve:", 
    "items": { 
     "1": "1", 
     "3": "3", 
     "5": "5" 
    }, 
    "rules": { 
     "range": "1-2" 
    } 
}, 
{ 
    "name": "showFoo", 
    "value": "on", 
    "label": "Show foo?" 
}, 
{ 
    "name": "title", 
    "value": "Foo", 
    "label": "Foo:" 
}] 

Tất cả trong một phiên bản dòng (thích hợp cho một chuỗi chữ):

[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}] 

Trong ví dụ trên, name , valuelabel là bắt buộc nhưng itemsrules là tùy chọn.

Đây là lớp tôi đang cố gắng để deserialize thành:

using System.Collections; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 

namespace foofoo 
{ 
    [DataContract] 
    public sealed class FooDef 
    { 
     [DataMember(Name = "name", IsRequired = true)] 
     public string Name { get; set; } 

     [DataMember(Name = "value", IsRequired = true)] 
     public string Value { get; set; } 

     [DataMember(Name = "label", IsRequired = true)] 
     public string Label { get; set; } 

     [DataMember(Name = "items", IsRequired = false)] 
     public Dictionary<string, string> Items { get; set; } 

     [DataMember(Name = "rules", IsRequired = false)] 
     public Dictionary<string, string> Rules { get; set; } 
    } 
} 

Dưới đây là đoạn code tôi sử dụng để deserialize:

var json = new DataContractJsonSerializer(typeof(List<FooDef>)); 
var bar = "[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]"; 
var stream = new MemoryStream(Encoding.UTF8.GetBytes(bar)); 
var foo = json.ReadObject(stream); 
stream.Close(); 

Tất cả mọi thứ đi khá tốt ngoại trừ việc itemsrules đang trống cho đầu tiên FooDef vượt qua. Tôi đã thử tất cả mọi thứ dưới ánh nắng mặt trời để thử và nhận được chúng: các lớp tùy chỉnh, NameValueCollection, KeyValuePair<string, string>, List của cả hai loại sau và mọi bộ sưu tập khác dường như áp dụng. [EDIT: Tôi quên thử Hashtable, mà dường như là một ứng cử viên rõ ràng. Đã không hoạt động.]

Vấn đề, như tôi thấy, là phần quan trọng bên dưới itemsrules là kết thúc mở. Tức là, không phải lúc nào cũng được gọi là range hoặc 3. Lời khuyên hay ý tưởng nào?

Trả lời

21

IMHO không có cách nào để deserialize chuỗi JSON bạn cung cấp vào một lớp .NET sử dụng DataContractJsonSerializer.

Sự cố xuất phát từ cách DataContractJsonSerializer tuần tự hóa từ điển. Bạn có thể sử dụng bộ nối tiếp thay thế như Json.NET (mà tôi đặc biệt khuyên dùng) hoặc JavaScriptSerializer (Tôi cho rằng nó không được sử dụng cho DataContractJsonSerializer nhưng nó sẽ hoạt động cho kịch bản của bạn).

Bạn cũng có thể đọc theserants.

Tài liệu: Serializing Collections - Json.NET

+0

Đó là những gì tôi lo ngại. Tôi đã tránh chuyển sang JavaScriptSerializer vì sự phản đối, nhưng tôi vui mừng khi biết rằng nó không được chấp nhận trong 3.5 SP1. Tôi sẽ thử nó bằng cách sử dụng lớp đó. – bbrown

+1

Tôi đã thử nó với JavaScriptSerializer và nó hoạt động hoàn hảo. Tôi đã kết thúc bằng cách sử dụng từ điển nhưng Hashtable cũng làm việc. – bbrown

+2

+1 cho Json.NET –