JToken से मौजूद मूल्य प्राप्त कर सकते हैं (सर्वोत्तम प्रथाएं)


117

JSON मानों का उपयोग करने के लिए सबसे अच्छा अभ्यास क्या है जो Json.NET का उपयोग करके C # में भी मौजूद नहीं हो सकता है ?

अभी मैं एक JSON प्रदाता के साथ काम कर रहा हूं जो JSON को लौटाता है जिसमें कभी-कभी कुछ कुंजी / मान जोड़े होते हैं, और कभी-कभी नहीं होते हैं। मैं अपने मूल्यों को प्राप्त करने के लिए (शायद गलत तरीके से) इस पद्धति का उपयोग कर रहा हूं (उदाहरण दोहरा पाने के लिए):

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

अब यह ठीक काम करता है, लेकिन जब उनमें से बहुत सारे हैं यह बोझिल है। मैंने एक एक्सटेंशन विधि लिखना समाप्त कर दिया, और केवल इसे लिखने के बाद मुझे आश्चर्य हुआ कि क्या मैं बेवकूफ हो रहा था ... वैसे भी, यहाँ विस्तार विधि है (मैं केवल दोहरे और स्ट्रिंग के लिए मामले शामिल करता हूं, लेकिन वास्तव में मेरे पास काफी कुछ है अधिक):

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;
}

और यहाँ विस्तार विधि का उपयोग करने का एक उदाहरण है:

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

BTW, कृपया क्षमा करें जो वास्तव में गूंगा प्रश्न हो सकता है, क्योंकि ऐसा लगता है कि कुछ ऐसा होना चाहिए जिसके लिए फ़ंक्शन में बनाया जाना चाहिए ... मैंने Google और Json.NET प्रलेखन की कोशिश की , हालांकि मैं समाधान खोजने में असमर्थ हूं। मेरा प्रश्न या दस्तावेज में यह स्पष्ट नहीं है।


मुझे पता है कि यह थोड़ा देर से है, लेकिन आप GetValueनीचे के इस सरलीकृत संस्करण को आजमाना चाह सकते हैं
LB

जवाबों:


210

यह जेनेरिक विधि Value()के लिए बहुत ज्यादा है। यदि आप इसे अशक्त मान प्रकार और ??ऑपरेटर के साथ जोड़ते हैं, तो आपको ठीक वैसा ही व्यवहार मिलता है, जैसा आप चाहते हैं :

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

4
यह एक विस्तार विधि है।
डेव वान डेन आईंडी

2
@PaHHazen, यह इतना बुरा नहीं है ... आपने बस पहिए को थोड़ा सा बदल दिया है।
डेविनबॉस्ट

यह काम नहीं करता है यदि "चौड़ाई" जोंस में मौजूद नहीं है और JToken अशक्त है
दीपक

2
@ डीकैप यह काम करता है यदि "चौड़ाई" मौजूद नहीं है। बेशक अगर यह काम नहीं करता jTokenहै null, लेकिन यह वह नहीं है जो सवाल पूछा है। और आप इसे आसानी से ठीक कर सकते हैं नल सशर्त ऑपरेटर का उपयोग करके width = jToken?.Value<double?>("width") ?? 100;:।
svick

1
JToken.Value<T>JToken एक JValue है, तो एक अपवाद फेंकता है
काइल डेलानी

22

मैं GetValueनीचे लिखूंगा

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;
}

इस तरह आप न केवल मूल प्रकार, बल्कि जटिल वस्तुओं के मूल्य भी प्राप्त कर सकते हैं। यहाँ एक नमूना है

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");

यह बहुत अच्छा है, लेकिन मुझे उन चिंताओं को अलग करना पसंद है जो केवल सरल डेटा प्रकार प्राप्त करने से मुझे मिलती हैं। हालांकि JSON की पार्सिंग की बात आने पर उस अलगाव की धारणा थोड़ी धुंधली है। चूंकि मैं एक पर्यवेक्षक / अवलोकन मॉडल (साथ ही mvvm के साथ) को लागू करता हूं, इसलिए मैं अपने सभी पार्सिंग को एक स्थान पर रखने के लिए, और इसे सरल रखता हूं (इसका एक हिस्सा मेरे लिए वापस लौटाए गए डेटा की अप्रत्याशितता भी है)।
पॉल हैन

@PaulHazen मैं यह नहीं कह सकता कि मैं आपको समझता हूं। आपका प्रश्न था retrieving JSON values that may not even existऔर मैंने प्रस्तावित किया था कि आपकी GetValueविधि बदलनी है । मुझे लगता है कि यह काम करता है कि आप कैसे चाहते हैं
LB

उम्मीद है कि मैं इस बार थोड़ा और स्पष्ट हो सकता हूं। आपका तरीका बहुत अच्छा काम करता है, और मैं जो चाहता हूं, वह पूरा होगा। हालांकि, मेरे प्रश्न में स्पष्ट नहीं किया गया अधिक संदर्भ यह है कि मैं जिस विशेष कोड पर काम कर रहा हूं वह कोड है जिसे मैं अत्यधिक हस्तांतरणीय होना चाहता हूं। हालांकि यह तर्कपूर्ण है कि आपका तरीका रास्ते में हो जाता है, यह GetValue <T> से वस्तुओं को हटाने की क्षमता का परिचय देता है, जो एक ऐसा पैटर्न है जो मैं अपने कोड को एक प्लेटफ़ॉर्म पर ले जाने के लिए बचना चाहता हूं जिसमें एक बेहतर Jee Parser (कहते हैं) , उदाहरण के लिए Win8)। इसलिए, मैंने जो पूछा, हां, आपका कोड एकदम सही होगा।
पॉल हैन

9

अगर टोकन मौजूद है तो आप यहां देख सकते हैं:

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

यह जांचता है कि "परिणाम" "परिणाम" में मौजूद है या नहीं।

यह एक अपवाद नहीं है जो अपवाद का कारण बनता है:

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

3

आप बस टाइपकास्ट कर सकते हैं, और यह आपके लिए रूपांतरण करेगा, जैसे

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

nullयदि उक्त कुंजी ऑब्जेक्ट में मौजूद नहीं है, तो यह स्वचालित रूप से वापस आ जाएगा , इसलिए इसके लिए परीक्षण करने की कोई आवश्यकता नहीं है।


1

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

जैसे

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


1

यह नल की देखभाल करता है

var body = JObject.Parse("anyjsonString");

body?.SelectToken("path-string-prop")?.ToString();

body?.SelectToken("path-double-prop")?.ToObject<double>();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.