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

C# 从JToken获取可能不存在的价值(最佳实践),c#,json.net,C#,Json.net,对于检索在C#using中甚至不存在的JSON值,最佳实践是什么 现在我正在处理一个JSON提供程序,它返回的JSON有时包含某些键/值对,有时不包含。我一直在使用(可能错误地)此方法获取我的值(例如获取双精度): 现在这很好,但是当有很多的时候,这很麻烦。我最终写了一个扩展方法,在写了它之后,我才怀疑自己是否愚蠢。。。无论如何,这里是扩展方法(我只包括double和string的情况,但实际上我还有很多): public static T GetValue(此JToken JToken,字符串

对于检索在C#using中甚至不存在的JSON值,最佳实践是什么

现在我正在处理一个JSON提供程序,它返回的JSON有时包含某些键/值对,有时不包含。我一直在使用(可能错误地)此方法获取我的值(例如获取双精度):

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

public static T GetValue(此JToken JToken,字符串键,
T默认值=默认值(T))
{
T返回值=默认值;
如果(jToken[key]!=null)
{
对象数据=null;
字符串sData=jToken[key].ToString();
类型=类型(T);
如果(类型为双精度)
data=double.Parse(sData);
else if(类型为string)
数据=sData;
if(null==data&&type.IsValueType)
抛出新ArgumentException(“无法分析类型\”+
type.FullName+“\”来自值\”+sData+“\”);
returnValue=(T)Convert.ChangeType(数据,
类型,CultureInfo.InvariantCulture);
}
返回值;
}
下面是一个使用扩展方法的示例:

width = jToken.GetValue<double>("width", 100);
width=jToken.GetValue(“宽度”,100);

顺便说一句,请原谅这可能是一个非常愚蠢的问题,因为它似乎应该有一个内置的功能为。。。我确实尝试过谷歌和文档,但是我要么找不到问题的解决方案,要么文档中不清楚。这就是通用方法的基本用途。如果将其与可为null的值类型和
??
运算符结合使用,则可以获得所需的行为:

width = jToken.Value<double?>("width") ?? 100;
width=jToken.Value(“宽度”)??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 static T GetValue(这个JToken JToken,字符串键,T defaultValue=default(T))
{
动态ret=jToken[key];
if(ret==null)返回defaultValue;
if(ret是JObject)返回JsonConvert.DeserializeObject(ret.ToString());
返回(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");
公共类ClassA
{
公共国际一级;
公共双D;
公共B类;
}
公共B类
{
公共国际一级;
公共字符串S;
}
varjt=JToken.Parse(“{I:1,D:3.5,ClassB:{I:2,S:'test'}”);
int i1=jt.GetValue(“I”);
双d1=jt.GetValue(“D”);
ClassB=jt.GetValue(“ClassB”);

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

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

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

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

if (jobject["Result"].SelectToken("Items") != null) { ... }
它检查“结果”中是否存在“项”

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

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

TYPE变量=jsonbody[“key”]?.Value()??默认值

e、 g


bool attachMap=jsonbody[“map”]?.Value()??虚假的

这会处理空值

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

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

body?.SelectToken("path-double-prop")?.ToObject<double>();
var body=JObject.Parse(“anyjsonString”);
body?.SelectToken(“路径字符串属性”)?.ToString();
body?.SelectToken(“路径双道具”)?.ToObject();

我知道有点晚了,但您可能想尝试下面的简化版
GetValue
string rootValue=jToken.Value()
这很酷,但我喜欢只获取简单数据类型所带来的关注点分离。尽管这种分离的概念在JSON解析中有点模糊。由于我实现了一个观察者/可观察模型(也使用mvvm),我倾向于将所有解析都放在一个地方,并保持简单(部分原因也是返回给我的数据的不可预测性)。@PaulHazen我不能说我理解你。您的问题是
检索可能根本不存在的JSON值
,我所建议的就是更改
GetValue
方法。我想这是你想要的。我这次可以说得更清楚一点。你的方法很有效,完全可以达到我的目的。然而,在我的问题中没有解释的更大的背景是,我正在处理的特定代码是我希望高度可转移的代码。虽然您的方法可能会造成阻碍,但它引入了从GetValue反序列化对象的功能,为了将代码移动到具有更好JSON解析器的平台(例如,Win8),我希望避免这种模式。所以,对于我所问的,是的,你的代码会很完美。@PaulHazen,没那么糟糕。。。如果json中不存在“宽度”,而JToken是,那么这就行不通了null@Deepak如果“宽度”不存在,它确实有效。当然,如果
jToken
null
,则它不起作用,但问题不是这样问的。您可以通过使用null条件运算符轻松地解决这个问题:
width=jToken?.Value(“width”)??100;
JToken.Value
如果JToken是处理大小写的JValueTo,则引发异常:
string ver=((JObject)标记).GetValue(“version”,StringComparison.OrdinalIgnoreCase)?.Value()
if (jobject["Result"]["Items"] != null) { ... }
var body = JObject.Parse("anyjsonString");

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

body?.SelectToken("path-double-prop")?.ToObject<double>();