System.Text.Json.JsonElement.GetString对数值失败



考虑这两个JSON:

{
"name": "John",
"age": 40
}

{
"name": "John",
"age": "40"
}

唯一的区别是,在一种情况下,40是一个数字,在另一种情况中,它是一个字符串。

我需要使用System.Text.Json解析这些JSON,但我的代码失败了:

System.InvalidOperationException:无法将令牌类型"Number"的值作为字符串获取。

我反序列化JSON,然后使用JsonElement.GetString()获取值。

我该怎么解决这个问题?

如果您有一个JsonElement,那么您可以使用它的ValueKind属性来确定它所代表的json的类型。

因此,例如,如果您解析了一个JsonDocument并检索了它的RootElement,那么JsonElementValueKind可以是ArrayObject

如果通过调用GetProperty得到JsonElement,则返回的JsonElementValueKind可以是任何预定义的值。


在您的特定示例中,您可以使用ValueKind来根据提取的属性的数据类型确定应调用哪个GetXYZ方法。

string input1 = "{"name": "John", "age": 40}";
string input2 = "{"name": "John", "age": "40"}";
foreach (var input in new[] { input1, input2 })
{
var doc = JsonDocument.Parse(input);
var age = doc.RootElement.GetProperty("age");
switch (age.ValueKind)
{
case JsonValueKind.Number:
{
var value = age.GetInt32();
Console.WriteLine($"{value} as a number");
break;
}
case JsonValueKind.String:
{
var value = age.GetString();
Console.WriteLine($"{value} as a text");
break;
}
default:
Console.WriteLine("unknown type");
break;
}
}

上面的代码有点脆弱,因为如果ValueKindNumber,我就选择了GetInt32。但是,如果你不知道数字的数据类型,那么你应该使用TryGetXYZ方法来尝试以安全的方式获取数字。

string input1 = "{"name": "John", "age": 40}";
string input2 = "{"name": "John", "age": "40"}";
string input3 = "{"name": "John", "age": 40.0}";
foreach (var input in new[] { input1, input2, input3 })
{
var doc = JsonDocument.Parse(input);
var age = doc.RootElement.GetProperty("age");
switch (age.ValueKind)
{
case JsonValueKind.Number:
{
if(age.TryGetInt32(out var integralNumber))
Console.WriteLine($"{integralNumber} as an integral number");
else if (age.TryGetDouble(out var floatingNumber))
Console.WriteLine($"{floatingNumber} as a floating number");
break;
}
case JsonValueKind.String:
{
var value = age.GetString();
Console.WriteLine($"{value} as a text");
break;
}
default:
Console.WriteLine("unknown type");
break;
}
}

最新更新