首页 > 解决方案 > 为什么 System.Text.Json.JsonElement 没有 TryGetString() 或 TryGetBoolean()

问题描述

我正在使用System.Text.Json返回JsonElement对象的 .NET Core 命名空间解析一些 JSON 数据。

例如,对于 Int32 类型,JsonElement有一个GetInt32()会将值作为整数返回,如果不是整数则抛出异常,还有一个TryGetInt32()将解析后的值复制到out变量并根据是否返回 true 或 false它能够正确解析。

这同样适用于几乎所有其他原始类型,但出于某种原因,GetBoolean()并且GetString()没有try...等效项,即使如果无法正确解析值,它们也会抛出异常。

这似乎是一个明显的疏忽,它让我觉得我做错了什么。谁能解释为什么不需要它们?

标签: c#jsonasp.net-coresystem.text.json

解决方案


UPD

不要介意最初的答案,这些TryGet_number_type方法不像我(我假设你)所期望的那样工作 - 如果你尝试从ValueKind不是 a 的元素Number(例如decimal文档)中获取“number_type”,它们会抛出。

因此,此TryGet...API 基本上尝试将内部值解析为某种具体类型,但前提是该尝试的具体类型的值是有效的json 类型Number(对于所有数字类型,forString和),否则它将抛出,因此没有意义有一个and方法,因为这里没有歧义(字符串总是字符串,布尔值总是布尔值),它们的行为与对应物完全相同。GuidDateTimeDateTimeOffsetInvalidOperationExceptionTryGetStringTryGetBooleanGet

原始答案

无法找到没有此 API 的任何理由,但自己实现它们应该不是一个大问题(在标准库中使用它们仍然会很好):

根据docs GetBoolean throws if value's ValueKindis not Truenor 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;
}

如果值既不是也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;
}

和样品测试:

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

推荐阅读