2012-03-06 47 views
79

Thực tiễn tốt nhất để truy xuất các giá trị JSON có thể không tồn tại trong C# bằng cách sử dụng Json.NET là gì?Nhận giá trị từ JToken có thể không tồn tại (thực tiễn tốt nhất)

Hiện tại tôi đang xử lý một nhà cung cấp JSON trả về JSON đôi khi chứa các cặp khóa/giá trị nhất định và đôi khi không có. Tôi đã sử dụng (có lẽ không chính xác) phương pháp này để lấy các giá trị của tôi (ví dụ để nhận được gấp đôi):

if(null != jToken["width"]) 
    width = double.Parse(jToken["width"].ToString()); 
else 
    width = 100; 

Bây giờ hoạt động tốt, nhưng khi có rất nhiều. Tôi đã kết thúc viết một phương pháp mở rộng, và chỉ sau khi viết nó đã làm tôi tự hỏi liệu có lẽ tôi đã được stupid ... anyways, đây là phương pháp mở rộng (tôi chỉ bao gồm các trường hợp cho đôi và chuỗi, nhưng trong thực tế tôi có khá một vài chi tiết):

public static T GetValue<T>(this JToken jToken, string key, 
          T defaultValue = default(T)) 
{ 
    T returnValue = defaultValue; 

    if (jToken[key] != null) 
    { 
     object data = null; 
     string sData = jToken[key].ToString(); 

     Type type = typeof(T); 

     if (type is double) 
      data = double.Parse(sData); 
     else if (type is string) 
      data = sData; 

     if (null == data && type.IsValueType) 
      throw new ArgumentException("Cannot parse type \"" + 
       type.FullName + "\" from value \"" + sData + "\""); 

     returnValue = (T)Convert.ChangeType(data, 
      type, CultureInfo.InvariantCulture); 
    } 

    return returnValue; 
} 

Và đây là một ví dụ của việc sử dụng các phương pháp khuyến nông:

width = jToken.GetValue<double>("width", 100); 

BTW, hãy tha thứ cho những gì có thể là một câu hỏi thực sự ngớ ngẩn, vì nó có vẻ giống như một cái gì đó có phải là một được xây dựng trong chức năng cho ... Tôi đã thử Google, và tài liệu Json.NET, tuy nhiên tôi là một trong hai t tìm giải pháp cho câu hỏi của tôi hoặc không rõ ràng trong tài liệu.

+0

Tôi biết nó là hơi muộn, nhưng bạn có thể muốn thử phiên bản đơn giản này của 'GetValue' dưới –

Trả lời

150

Đây là phương pháp chung chung của phương pháp chung Value(). Bạn nhận được chính xác những hành vi mà bạn muốn nếu bạn kết hợp nó với các loại giá trị nullable và ?? điều hành:

width = jToken.Value<double?>("width") ?? 100; 
+2

Cảm ơn @svick! Đó chính xác là những gì tôi đang tìm kiếm. Như tôi nghi ngờ nó là một cái gì đó đơn giản, tương tự, và đã có tại chỗ.* mặt cọ * –

+3

Đó là một phương pháp mở rộng. –

+1

@PaulHazen, nó không phải là xấu ... Bạn chỉ cần phát minh lại bánh xe một chút là tất cả. – devinbost

12

Tôi sẽ viết GetValue như sau

public static T GetValue<T>(this JToken jToken, string key, T defaultValue = default(T)) 
{ 
    dynamic ret = jToken[key]; 
    if (ret == null) return defaultValue; 
    if (ret is JObject) return JsonConvert.DeserializeObject<T>(ret.ToString()); 
    return (T)ret; 
} 

Bằng cách này bạn có thể nhận được giá trị của không chỉ các loại cơ bản nhưng cũng là các đối tượng phức tạp. Dưới đây là mẫu

public class ClassA 
{ 
    public int I; 
    public double D; 
    public ClassB ClassB; 
} 
public class ClassB 
{ 
    public int I; 
    public string S; 
} 

var jt = JToken.Parse("{ I:1, D:3.5, ClassB:{I:2, S:'test'} }"); 

int i1 = jt.GetValue<int>("I"); 
double d1 = jt.GetValue<double>("D"); 
ClassB b = jt.GetValue<ClassB>("ClassB"); 
+0

Đó là khá mát mẻ, nhưng tôi thích sự tách biệt của mối quan tâm mà chỉ nhận được các loại dữ liệu đơn giản mang lại cho tôi. Mặc dù khái niệm về sự tách biệt đó bị mờ một chút khi nói đến phân tích cú pháp JSON. Vì tôi thực hiện một mô hình quan sát/quan sát (với mvvm), tôi có xu hướng giữ tất cả phân tích của mình ở một nơi và giữ nó đơn giản (một phần trong đó cũng là khả năng không thể đoán trước của dữ liệu được trả lại cho tôi). –

+0

@PaulHazen Tôi không thể nói rằng tôi hiểu bạn. Câu hỏi của bạn là 'lấy các giá trị JSON có thể không tồn tại' và tất cả những gì tôi đề xuất là thay đổi phương thức' GetValue' của bạn. Tôi nghĩ rằng nó hoạt động như thế nào bạn muốn –

+0

Hy vọng rằng tôi có thể được một chút rõ ràng hơn thời gian này. Phương pháp của bạn hoạt động tốt và hoàn thành chính xác những gì tôi muốn. Tuy nhiên, bối cảnh lớn hơn không được giải thích trong câu hỏi của tôi là mã cụ thể mà tôi đang làm là mã mà tôi muốn được chuyển nhượng cao. Trong khi nó cho rằng phương thức của bạn bị cản trở, nó giới thiệu khả năng deserialize các đối tượng từ GetValue , là một mẫu mà tôi muốn tránh vì chuyển mã của tôi sang nền tảng có trình phân tích cú pháp JSON tốt hơn (ví dụ, Win8 ví dụ). Vì vậy, đối với những gì tôi hỏi, có, mã của bạn sẽ được hoàn hảo. –

2

Bạn có thể chỉ cần nhập và sẽ thực hiện chuyển đổi cho bạn, ví dụ:

var with = (double?) jToken[key] ?? 100; 

Nó sẽ tự động trả lại null nếu phím không có trong đối tượng, vì vậy không cần phải kiểm tra.

3

Đây là cách bạn có thể kiểm tra nếu token tồn tại:

if (jobject["Result"].SelectToken("Items") != null) { ... } 

Nó sẽ kiểm tra nếu "Items" tồn tại trong "kết quả".

Đây là một ví dụ KHÔNG làm việc gây ra ngoại lệ:

if (jobject["Result"]["Items"] != null) { ... } 
0

TYPE variable = jsonbody["key"]?.Value<TYPE>() ?? DEFAULT_VALUE;

ví dụ

bool attachMap = jsonbody["map"]?.Value<bool>() ?? false;

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