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

本文关键字:最佳 获取 不存在 JToken | 更新日期: 2023-09-27 18:27:01

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

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

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

现在,这很好,但当它们很多的时候,就很麻烦了。我最终写了一个扩展方法,只有在写了它之后,我才怀疑自己是否愚蠢。。。不管怎样,这里是扩展方法(我只包括double和string的情况,但实际上我还有很多):

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

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

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

这几乎就是通用方法Value()的作用。如果将其与可为null的值类型和??运算符结合使用,则可以获得所需的行为:

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

我会将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");

以下是如何检查令牌是否存在:

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

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

这是一个导致异常的不工作示例:

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

您可以简单地进行类型转换,它会为您进行转换,例如

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

如果所述密钥不在对象中,则它将自动返回null,因此无需对其进行测试。

这会处理空

var body = JObject.Parse("anyjsonString");
body?.SelectToken("path-string-prop")?.ToString();
body?.SelectToken("path-double-prop")?.ToObject<double>();

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

例如

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