从JToken获取可能不存在的价值(最佳实践)

Pau*_*zen 106 c# json.net

使用Json.NET检索C#中甚至可能不存在的JSON值的最佳实践是什么?

现在我正在处理一个JSON提供程序,它返回有时包含某些键/值对的JSON,有时则不然.我一直在使用(也许是错误的)这个方法来获取我的值(例如获得一个double):

if(null != jToken["width"])
    width = double.Parse(jToken["width"].ToString());
else
    width = 100;
Run Code Online (Sandbox Code Playgroud)

现在它工作正常,但是当它们很多时它很麻烦.我最后编写了一个扩展方法,并且只有写完之后我才会想知道是否我是愚蠢的......反正这里是扩展方法(我只包括双和字符串的情况,但实际上我有很多更多):

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;
}
Run Code Online (Sandbox Code Playgroud)

这是使用扩展方法的示例:

width = jToken.GetValue<double>("width", 100);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,请原谅可能是一个非常愚蠢的问题,因为它似乎应该有一个内置函数...我确实尝试了谷歌和Json.NET文档,但是我要么找不到解决方案我的问题或在文档中不清楚.

svi*_*ick 198

这几乎是泛型方法Value()的用途.如果将它与可空值类型和??运算符组合,您将获得所需的行为:

width = jToken.Value<double?>("width") ?? 100;
Run Code Online (Sandbox Code Playgroud)

  • 这是一种扩展方法. (3认同)
  • 谢谢@svick!这正是我想要的.我怀疑这是一个简单,类似,已经到位的东西.*面掌* (2认同)
  • @PaulHazen,还不错……你只是重新发明了轮子而已。 (2认同)
  • @Deepak如果“宽度”不存在,它将起作用。如果`jToken`为`null`当然是行不通的,但这不是问题要问的。而且,您可以使用空条件运算符轻松地解决此问题:`width = jToken?.Value &lt;double?&gt;(“ width”)?100;`。 (2认同)
  • 如果 JToken 是 JValue,则 `JToken.Value&lt;T&gt;` 会引发异常 (2认同)
  • 处理大小写:`string ver = ((JObject)token).GetValue("version", StringComparison.OrdinalIgnoreCase)?.Value&lt;string&gt;();` /sf/answers/3492067771/ (2认同)

L.B*_*L.B 18

我会写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;
}
Run Code Online (Sandbox Code Playgroud)

这样,您不仅可以获得基本类型的值,还可以获得复杂对象的值.这是一个例子

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");
Run Code Online (Sandbox Code Playgroud)


Art*_*eev 6

这是检查令牌是否存在的方法:

if (jobject["Result"].SelectToken("Items") != null) { ... }
Run Code Online (Sandbox Code Playgroud)

它检查“结果”中是否存在“项目”。

这是一个导致异常的无效示例:

if (jobject["Result"]["Items"] != null) { ... }
Run Code Online (Sandbox Code Playgroud)