2013-12-12 18 views
5

Tôi đang sử dụng C# để deserialize một tập hợp các chuỗi JSON. Mỗi chuỗi có một thuộc tính employer_normalized được cho là chứa stringList<int> trong đó các giá trị trong List luôn là số dương. Trong một số trường hợp, employer_normalized được đặt thành -1, vì vậy tôi muốn ghi đè các trường hợp này với một số hành vi đặt employer_normalized thành null.Deserialize JSON có thể là số nguyên hoặc danh sách các chuỗi trong C#

Đây là lớp học của tôi:

public class EmployerNormalized 
{ 
    public string company; 
    public List<int> code; 
} 

Tốt JSON

"employer_normalized": { 
     "company": "self", 
     "code": [ 
      "4581 ", 
      "6732 ", 
      "9121", 
      "9999 ", 
      "5947 ", 
      "8322 ", 
      "8351 ", 
      "7335 ", 
      "9999 ", 
      "4225 ", 
      "8399 " 
     ] 
     } 

Bad JSON

"employer_normalized": -1 

Tôi hiện đang sử dụng Json.NET để làm phân tích cú pháp JSON của tôi. Giải pháp thanh lịch để giải quyết vấn đề này là gì? Tốt nhất là chỉ cần đặt giá trị employer_normalized thành null nếu đó là -1? Nếu vậy, làm thế nào tôi có thể làm điều này?

+2

cháy bất cứ ai phát triển ứng dụng mà tạo ra JSON này :) –

+0

Tôi ước gì tôi có thể. Tôi đang mắc kẹt với điều này cho bây giờ, mặc dù, vì vậy tôi đã phải tìm ra một cách để xử lý những trường hợp cụ thể. – RouteMapper

Trả lời

3

Bạn có thể sử dụng JsonConverter tùy chỉnh để xử lý tình huống này. Bất cứ nơi nào bạn đang mong đợi một EmployerNormalized, bộ chuyển đổi có thể kiểm tra xem giá trị của thuộc tính đó là -1 và trả về null, nếu không thì deserialize nó bình thường.

Đây là mã cho bộ chuyển đổi:

public class EmployerNormalizedConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(EmployerNormalized)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JToken token = JToken.Load(reader); 
     if (token.Type == JTokenType.Object) 
     { 
      return token.ToObject<EmployerNormalized>(); 
     } 
     return null; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Và đây là một bản demo cho thấy làm thế nào để sử dụng nó:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @" 
     { 
      ""good"" : { 
       ""company"": ""self"", 
       ""code"": [ 
        ""4581 "", 
        ""6732 "", 
        ""9121"", 
        ""9999 "", 
        ""5947 "", 
        ""8322 "", 
        ""8351 "", 
        ""7335 "", 
        ""9999 "", 
        ""4225 "", 
        ""8399 "" 
       ] 
      }, 
      ""bad"" : -1 
     }"; 

     Wrapper wrapper = 
      JsonConvert.DeserializeObject<Wrapper>(json, 
       new EmployerNormalizedConverter()); 

     DumpEmployer("good", wrapper.good); 
     DumpEmployer("bad", wrapper.bad); 
    } 

    private static void DumpEmployer(string prop, EmployerNormalized emp) 
    { 
     Console.WriteLine(prop); 
     if (emp != null) 
     { 
      Console.WriteLine(" company: " + emp.company); 
      Console.WriteLine(" codes: " + 
       string.Join(", ", emp.code.Select(c => c.ToString()))); 
     } 
     else 
      Console.WriteLine(" (null)"); 
    } 

    public class Wrapper 
    { 
     public EmployerNormalized good { get; set; } 
     public EmployerNormalized bad { get; set; } 
    } 

    public class EmployerNormalized 
    { 
     public string company; 
     public List<int> code; 
    } 
} 

Dưới đây là kết quả:

good 
    company: self 
    codes: 4581, 6732, 9121, 9999, 5947, 8322, 8351, 7335, 9999, 4225, 8399 
bad 
    (null) 

Lưu ý quan trọng: Bạn có thể bị cám dỗ để trang trí EmployerNormalized lớp học với [JsonConverter(typeof(EmployerNormalizedConverter))], nhưng nếu bạn làm điều đó, sau đó chuyển đổi, ở dạng hiện tại của nó, sẽ kết thúc lên gọi chính nó đệ quy cho đến khi nó lỗi ra với một StackOverflowException. Nếu bạn cần/muốn sử dụng thuộc tính, thì mã của phương thức ReadJson trong trình chuyển đổi sẽ cần được thay đổi để tạo thủ công một cá thể của lớp EmployerNormalized và điền tất cả các thuộc tính riêng lẻ thay vì gọi token.ToObject<EmployerNormalized>(). Dưới đây là một phiên bản thay thế của ReadJson rằng sẽ tránh được những vấn đề đệ quy:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    JToken token = JToken.Load(reader); 
    if (token.Type == JTokenType.Object) 
    { 
     EmployerNormalized employer = new EmployerNormalized(); 
     employer.company = token["company"].ToString(); 
     employer.code = token["code"].ToObject<List<int>>(); 
     return employer; 
    } 
    return null; 
} 
+0

Đây là HOÀN THÀNH! Cảm ơn bạn! – RouteMapper

+0

Không sao cả; rất vui được giúp đỡ. –

+0

Bất kỳ ý tưởng nào tại sao tôi có thể gặp lỗi này? 'Một ngoại lệ không được xử lý kiểu 'System.StackOverflowException' xảy ra trong Newtonsoft.Json.dll'. Tôi đang xử lý một danh sách các đối tượng có chứa một đối tượng 'EmployerNormalized'. – RouteMapper

1

Tôi biết điều này sucks, nhưng trước tiên bạn có thể thử để phân tích JSON string một Object với cấu trúc của bạn tốt JSON, và trong trường hợp phân tích lỗi, phân tích đối với trường hợp thứ hai (Bad JSON).

+0

Vì vậy, bạn có nghĩa là tôi nên tạo một lớp đại diện cho JSON xấu và phân tích cú pháp đó trong trường hợp ngoại lệ? – RouteMapper

+0

Khá nhiều - * lúng túng * – everton

+0

Tôi nghĩ giải pháp đơn giản nhất là chỉ cần đặt 'employ_normalized' thành' null', nhưng tôi chỉ cần lưu ý điều đó vì tôi định chèn các bản ghi này vào cơ sở dữ liệu. DB của tôi sẽ hét lên nếu tôi chèn một giá trị 'null' vào một trường không nullable. Ugh! – RouteMapper

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