I'm parsing some JSON data with the .NET Core System.Text.Json
namespace which returns JsonElement
objects.
For Int32 types, for example, JsonElement
has a GetInt32()
which will return the value as an integer or throw an exception if it isn't an integer, and there is also a TryGetInt32()
which copies the parsed value to an out
variable and returns true or false depending on whether it was able to parse correctly.
The same applies to almost all other primitive types but for some reason, GetBoolean()
and GetString()
have no try...
equivalent even though they also will throw an exception if the value cannot be parsed correctly.
This seems such an obvious oversight, it makes me think I'm doing something wrong. Can anyone explain why they aren't needed?
UPD
Don't mind the original answer, the TryGet_number_type
methods don't work as I (and I assume you) would expect - they will throw if you will try to get "number_type" from element which ValueKind
is not a Number
(decimal
docs for example).
So this TryGet...
API basically tries to parse inner value as some concrete type but only if value is of valid json type for this attempted concrete type(Number
for all numeric types, String
for Guid
, DateTime
and DateTimeOffset
), otherwise it will throw InvalidOperationException
, therefore it would not make sense to have an TryGetString
and TryGetBoolean
methods because there is no ambiguity here (string is always a string and boolean is always a boolean) and they would behave exactly the same as Get
counterpart.
Original answer:
Was not able to find any reasoning for not having this API's, but implementing them yourself should not be a big issue (still would be nice to have them in standard library):
According to docs GetBoolean
throws if value's ValueKind
is neither True
nor 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;
}
And GetString
throws if value's ValueKind
is neither String
nor Null
:
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;
}
And sample test:
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);
}
}