Reputation: 2814
So when I have a JsonNode I can just ask if it's a JsonObject or a JsonArray and work with those. But when the node is an actual value, how do I know whether it's a string, number or boolean?
Of course I could just try and parse the value, but then a number transmitted in a string would become a number instead of a string which I'd like to avoid.
I'm using System.Text.Json with .NET 6.
Upvotes: 20
Views: 17149
Reputation: 86
The following code works in .NET fiddle with .NET 6.
Note:
JsonValue
ultimately came from a JsonNode.Parse*(...)
, then your JsonValue
will contain a "JSON type".JsonValue
was created using JsonValue.Create()
or an implicit conversion, then your JsonValue
will contain a "CLR type".JsonValue.GetValue<T>()
only does type conversion if JsonValue
contains a "JSON type".JsonValue.GetValue<object>()
conveniently returns the underlying value, which is a JsonElement
if it is a "JSON type".public static class JsonValueExtensions
{
public static Type GetValueType(this JsonValue jsonValue)
{
var value = jsonValue.GetValue<object>();
if (value is JsonElement element)
{
return element.ValueKind switch
{
JsonValueKind.False => typeof(bool),
JsonValueKind.True => typeof(bool),
JsonValueKind.Number => typeof(double),
JsonValueKind.String => typeof(string),
var _ => typeof(JsonElement),
};
}
return value.GetType();
}
}
Upvotes: 6
Reputation: 95
Depending on the type of JsonElement returned you have to handle it differently.
My case was that the returned element was ValueKind = Array : "[[47.751]]" So in order to get it I did created this method
private object GetValueFromJsonElement(WorkbookRange range)
{
var element = range.Values.RootElement.EnumerateArray().First()[0];
switch (element.ValueKind)
{
case JsonValueKind.Number:
return element.GetDouble();
case JsonValueKind.String:
return element.GetString();
case JsonValueKind.True:
case JsonValueKind.False:
return element.GetBoolean();
default:
throw new InvalidOperationException("The Value Type returned is not handled");
}
}
Upvotes: 3
Reputation: 587
The accepted answer only works for specific use cases, namely that the node in question is of type JsonValue.
I propose a better option is to first test for the basic kind of types there are in JSON.
someObject["SomeNode"] is JsonArray
someObject["SomeNode"] is JsonObject
someObject["SomeNode"] is JsonValue
if the object is of type JsonValue one can use tryGetvalue to directly test for the expected value type
someObject["SomeNode"].AsValue().TryGetValue<someType>(out someType result)
TryGetValue returns true if it the value was parseble as the requested type.
If the expected type is completely unknown or variable (ugh), you could use the
someObject["SomeNode"].GetValue<JsonElement>().ValueKind
trick. But that only works for distinquishing between int and string and the bool values. Trying this on an array will give an exception. Therefore you first have to test with the "is" style syntax above.
Upvotes: 8
Reputation: 42245
From the source, it looks like a JsonValue
just wraps a JsonElement
. So you can do .GetValue<JsonElement>()
(which passes this check), and then inspect its ValueKind
property.
Upvotes: 8
Reputation: 494
Each JsonProperty has two properties - Name and Value of Type JsonElement. JsonElement has an Enum property named ValueKind which can help you determine what of what data type your JSON value is.
You can get JsonProperties by calling .EnumerateObject() on your JsonElement. You can work with your Json document as a JsonElement instead of JsonObject.
Upvotes: 2