And*_*ndy 13 c# json asp.net-core system.text.json
System.Text.Json我正在使用返回对象的.NET Core 命名空间解析一些 JSON 数据JsonElement。
例如,对于 Int32 类型,JsonElement有一个GetInt32()将值作为整数返回,如果不是整数则抛出异常,还有一个TryGetInt32()将解析后的值复制到out变量并返回 true 或 false,具体取决于是否它能够正确解析。
这同样适用于几乎所有其他基本类型,但由于某种原因,GetBoolean()并且GetString()没有try...等效项,即使如果无法正确解析值,它们也会抛出异常。
这似乎是一个明显的疏忽,它让我觉得我做错了什么。谁能解释为什么不需要它们?
UPD
不要介意原来的答案,这些TryGet_number_type方法不会像我(我假设你)期望的那样工作 - 如果你尝试从ValueKind不是 a 的元素中获取“number_type” Number(例如decimal文档),它们会抛出异常。
因此,这个API 基本上尝试将内部值解析为某种具体类型TryGet...,但前提是该尝试的具体类型的值是有效的json 类型Number(对于所有数字类型,StringforGuid和),否则它将抛出,因此没有意义有一个and方法,因为这里没有歧义(字符串始终是字符串,布尔值始终是布尔值),并且它们的行为与对应的完全相同。DateTimeDateTimeOffsetInvalidOperationExceptionTryGetStringTryGetBooleanGet
原答案:
无法找到没有这个 API 的任何理由,但自己实现它们应该不是一个大问题(仍然很好将它们包含在标准库中):
根据文档, GetBoolean如果值ValueKind既不是也不True是,则抛出异常False。
public static bool TryGetBoolean(this JsonElement je, out bool parsed)
{
var (p, r) = je.ValueKind switch
{
JsonValueKind.True => (true, true),
JsonValueKind.False => (false, true),
_ => (default, false)
};
parsed = p;
return r;
}
Run Code Online (Sandbox Code Playgroud)
如果值既不是也不是则GetString 抛出:ValueKindStringNull
public static bool TryGetsString(this JsonElement je, out string parsed)
{
var (p, r) = je.ValueKind switch
{
JsonValueKind.String => (je.GetString(), true),
JsonValueKind.Null => (null, true),
_ => (default, false)
};
parsed = p;
return r;
}
Run Code Online (Sandbox Code Playgroud)
以及样本测试:
using (JsonDocument document = JsonDocument.Parse(@"{""bool"": true, ""str"": ""string""}"))
{
if (document.RootElement.GetProperty("bool").TryGetBoolean(out var b))
{
Console.WriteLine(b);
}
if (document.RootElement.GetProperty("str").TryGetString( out var s))
{
Console.WriteLine(s);
}
}
Run Code Online (Sandbox Code Playgroud)
文档注释中的注释似乎暗示了答案(但没有完全解释) :
\n\n\n此方法不解析 JSON 字符串值的内容。
\n
但我仍然很困惑,直到我在 github 问题中发现了一些描述这些方法的评论。这是该评论的片段(稍微省略,**由我添加):
// InvalidOperationException if Type is not True or False\npublic bool GetBoolean();\n\n// InvalidOperationException if Type is not Number \n// FormatException if value does not fit \npublic decimal GetDecimal(); \npublic double GetDouble(); \npublic int GetInt32(); \n\n// InvalidOperationException if Type is not Number\n// false if value **does not fit.** \npublic bool TryGetDecimal(out decimal value); \npublic bool TryGetDouble(out double value); \npublic bool TryGetInt32(out int value);\nRun Code Online (Sandbox Code Playgroud)\n因此,最终归结为 aFormatException和 an之间的区别InvalidOperationException。
后者用于指示标记ValueKind(数字、字符串、True、False)与预期类型不匹配。前一个 ( FormatException) 的使用有点偏离标签,超出了人们通常的预期;它不是因解析错误*(即“1.sg”不是 )而抛出,而是因超出范围错误int而抛出!
如果我们首先看看数字重载,就会更好地理解这一点。非Try变量要么返回一个值,要么抛出两个异常之一:InvalidOperationException如果值不是数字,FormatExceptions如果它们不适合。从文档中GetInt32:
\n\n例外情况
\n\n
InvalidOperationException该值的\xc2\xa0
\nValueKind\xc2\xa0 不是\xc2\xa0Number。\n
FormatException该值不能表示为
\nInt32。
将此与Try抛出一个异常的变体(InvalidOperationException如果类型不是数字)进行比较,但如果值不适合则返回。 false从文档中TryGetInt32:
\n\n例外情况
\n\n
InvalidOperationException该值的\xc2\xa0
\nValueKind\xc2\xa0 不是\xc2\xa0Number。退货
\n布尔值
\ntrue\xc2\xa0 如果数字可以表示为Int32; 否则,\xc2\xa0false。
在这种情况下,“不适合”意味着该值对于基础类型来说太大/太小,即。大于int.MaxValue使用时[Try]GetInt32
现在让我们回到booleans您正确地注意到只有一个非Try变体的情况。查看同一 github 问题中的评论,我们看到:
// InvalidOperationException if Type is not True or False\npublic bool GetBoolean();\nRun Code Online (Sandbox Code Playgroud)\n和文档:
\n\n\n例外情况
\n\n
InvalidOperationException该值的\xc2\xa0
\nValueKind\xc2\xa0 既不是True也不是False。
这里缺少的是FormatException“不适合”的情况。正如我们在上面看到的数字情况,该Try变体让我们检测到“是的,这是一个数字,但它超出了适当的范围”。Booleans只有两个可能的值——true并且false——没有范围可检测,也没有FormatException可区分。与strings--it 类似,要么是string令牌,要么不是。
需要注意的是,在所有情况下,InvalidOperationException如果ValueKind与方法所期望的不匹配,就会抛出异常。如果假设遇到“abc”值,则TryGetBoolean不会返回,它会抛出一个,因为不是或。但这已经是这样了!因此不需要单独的方法。falsestringInvalidOperationExceptionValueKindTrueFalseGetBoolean
*注意:没有解析错误,因为这些方法实际上并不尝试解析json令牌内的数字/布尔值string,它们只考虑正确令牌类型的值。换句话说,当前不支持引用的数字/布尔值:
{\n "number": 1234,\n "notNumber": "1234",\n "bool": true,\n "notBool": "false"\n}\nRun Code Online (Sandbox Code Playgroud)\n目前(2020-05-30)请求添加对此的支持。届时我们可能会看到方法的可用性/功能发生变化TryGet。
| 归档时间: |
|
| 查看次数: |
8236 次 |
| 最近记录: |