2011-10-04 28 views
5

Tôi sử dụng DataContractJsonSerializer để phân tích cú pháp một chuỗi json thành một phân cấp đối tượng. Chuỗi json trông giống như sau:C# DataContractJsonSerializer không thành công khi giá trị có thể là một mảng hoặc một mục duy nhất

{ 
    "groups": [ 
     { 
      "attributes": [ 
       { 
        "sortOrder": "1", 
        "value": "A" 
       }, 
       { 
        "sortOrder": "2", 
        "value": "B" 
       } 
      ] 
     }, 
     { 
      "attributes": { 
       "sortOrder": "1", 
       "value": "C" 
      } 
     } 
    ] 
} 

Như bạn có thể thấy giá trị phụ của "thuộc tính" có thể là một mảng hoặc một mục duy nhất. Tôi đã tìm thấy phần mã nơi sự cố xảy ra:

[DataContract] 
public class ItemGroup 
{ 
    [DataMember(Name="attributes")] 
    public List<DetailItem> Items { get; set; } 
} 

Làm việc đầu tiên nhưng không hoạt động ở lần thứ hai.

Có ai trả lời câu hỏi này không?

Thx

+0

tại sao json không phù hợp với điều này? sẽ sửa chữa tại nguồn là có thể? –

+0

Làm thế nào nó không thành công? Lỗi gì? – bryanmac

Trả lời

3

Nếu bạn kiểm soát cách tạo JSON thì hãy đảm bảo rằng thuộc tính là mảng ngay cả khi chỉ chứa một phần tử. Sau đó, phần tử thứ hai sẽ trông như thế này và phân tích cú pháp tốt.

{ 
     "attributes": [{ 
      "sortOrder": "1", 
      "value": "C" 
     }] 
    } 
3

Như Daniel đã nói, nếu bạn có thể kiểm soát việc tạo Json, tốt hơn là tiếp tục theo cách đó. Nhưng nếu bạn không thể, sau đó bạn có thể sử dụng thư viện Json.Net & lớp JSONObject từ this liên kết để viết một số mã như:

JObject o = (JObject)JsonConvert.DeserializeObject(input); 
dynamic json = new JsonObject(o); 
foreach (var x in json.groups) 
{ 
     var attrs = x.attributes; 
     if (attrs is JArray) 
     { 
      foreach (var y in attrs) 
      { 
       Console.WriteLine(y.value); 
      } 
     } 
     else 
     { 
      Console.WriteLine(attrs.value); 
     } 
} 
+0

Đó là một ý tưởng hay –

1

Tôi cố gắng để có được điều này làm việc với DataContractJsonSerializer, JavaScriptSerializer, và JSON .Net và không có deserialize trực tiếp đến một đối tượng thành công trong mọi trường hợp. Tôi đã sử dụng một phương pháp tương tự như L.B, sử dụng JSON.Net, mặc dù không sử dụng các động lực và lớp JsonObject bổ sung. Thích ứng với mã của tôi để kịch bản của bạn sẽ trông giống như sau:

private List<ItemGroup> ParseItemGroupList(string input) 
    { 
     JObject json = JObject.Parse(input); 

     List<ItemGroup> groups = new List<ItemGroup>(); 
     JArray gArray = json["groups"] as JArray; 
     foreach (var gToken in gArray) 
     { 
      ItemGroup newGroup = new ItemGroup(); 
      JToken attrToken = gToken["attributes"] as JToken; 
      if (attrToken is JArray) 
      { 
       newGroup.Items = attrToken.Children().Select(MapDetailItem()).ToList(); 
      } 
      else 
      { 
       newGroup.Items = new List<DetailItem>() { MapDetailItem().Invoke(attrToken) }; 
      } 

      groups.Add(newGroup); 
     } 

     return groups; 
    } 

    private static Func<JToken, DetailItem> MapDetailItem() 
    { 
     return json => new DetailItem 
     { 
      SortOrder = (string)json["sortOrder"], 
      Value = (string)json["value"] 
     }; 
    } 

Hy vọng rằng, ai đó sẽ thêm một thiết lập cho JSON.Net để cho phép nó để buộc deserialization đến một bộ sưu tập với một mục duy nhất chứ không phải ném một ngoại lệ. Đó là một sự xấu hổ mà bạn phải làm tất cả các phân tích cú pháp theo cách thủ công khi chỉ có một phần nhỏ của JSON không phân tích cú pháp một cách chính xác tự động.

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