Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ public override T GetValue<T>()
public override bool TryGetValue<T>([NotNullWhen(true)] out T? value)
where T : default
{
if (typeof(T) == typeof(JsonElement))
if (typeof(T) == typeof(JsonElement) || typeof(T) == typeof(JsonElement?))
{
value = (T)(object)JsonWriterHelper.WriteString(_value.Span, static serialized => JsonElement.Parse(serialized));
return true;
}

if (typeof(T) == typeof(string))
if (typeof(T) == typeof(string) || typeof(T) == typeof(object))
{
string? result = JsonReaderHelper.TranscodeHelper(_value.Span);

Expand Down Expand Up @@ -150,13 +150,13 @@ public override T GetValue<T>()
public override bool TryGetValue<T>([NotNullWhen(true)] out T? value)
where T : default
{
if (typeof(T) == typeof(JsonElement))
if (typeof(T) == typeof(JsonElement) || typeof(T) == typeof(JsonElement?))
{
value = (T)(object)JsonElement.Parse(_value ? JsonConstants.TrueValue : JsonConstants.FalseValue);
return true;
}

if (typeof(T) == typeof(bool) || typeof(T) == typeof(bool?))
if (typeof(T) == typeof(bool) || typeof(T) == typeof(bool?) || typeof(T) == typeof(object))
{
value = (T)(object)_value;
return true;
Expand Down Expand Up @@ -197,7 +197,7 @@ public override T GetValue<T>()
public override bool TryGetValue<T>([NotNullWhen(true)] out T? value)
where T : default
{
if (typeof(T) == typeof(JsonElement))
if (typeof(T) == typeof(JsonElement) || typeof(T) == typeof(JsonElement?) || typeof(T) == typeof(object))
{
value = (T)(object)JsonElement.Parse(_value);
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public static void TryGetValue_FromString()
JsonValue jValue = JsonNode.Parse("\"MyString\"").AsValue();

Assert.True(jValue.TryGetValue(out string _));
Assert.True(jValue.TryGetValue(out object _));
Assert.False(jValue.TryGetValue(out char _));
Assert.False(jValue.TryGetValue(out byte _));
Assert.False(jValue.TryGetValue(out short _));
Expand Down Expand Up @@ -147,6 +148,7 @@ public static void TryGetValue_FromNumber()
Assert.True(jValue.TryGetValue(out float _));
Assert.True(jValue.TryGetValue(out double _));
Assert.True(jValue.TryGetValue(out decimal _));
Assert.True(jValue.TryGetValue(out object _));
Assert.False(jValue.TryGetValue(out bool _));
Assert.False(jValue.TryGetValue(out string _));
Assert.False(jValue.TryGetValue(out char _));
Expand Down Expand Up @@ -211,6 +213,7 @@ public static void TryGetValue_FromBoolean()
JsonValue jValue = JsonNode.Parse("true").AsValue();

Assert.True(jValue.TryGetValue(out bool _));
Assert.True(jValue.TryGetValue(out object _));
Assert.False(jValue.TryGetValue(out byte _));
Assert.False(jValue.TryGetValue(out short _));
Assert.False(jValue.TryGetValue(out int _));
Expand All @@ -229,6 +232,48 @@ public static void TryGetValue_FromBoolean()
Assert.False(jValue.TryGetValue(out Guid _));
}

[Theory]
[InlineData("\"Hello World!\"", typeof(string))]
[InlineData("42", typeof(JsonElement))]
[InlineData("true", typeof(bool))]
[InlineData("false", typeof(bool))]
public static void GetValue_Object(string json, Type expectedType)
{
JsonValue jValue = JsonSerializer.Deserialize<JsonValue>(json);

object result = jValue.GetValue<object>();
Assert.NotNull(result);
Assert.IsType(expectedType, result);
}
Comment on lines +235 to +247
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new GetValue_Object theory asserts that GetValue() returns different runtime types per primitive (string/bool return CLR primitives, number returns JsonElement). This bakes in a potentially breaking behavioral change vs .NET 9’s JsonValueOfElement (where object yielded JsonElement for all primitives) and vs JsonNode.Parse(...) today. Please confirm the intended API behavior and adjust expectations/docs to avoid inconsistent results depending on how the node was created.

Copilot uses AI. Check for mistakes.

[Fact]
public static void TryGetValue_NullableTypes_Deserialized()
{
// String primitive (JsonValueOfJsonString): JsonElement? should work
JsonValue stringValue = JsonSerializer.Deserialize<JsonValue>("\"Hello\"");
Assert.True(stringValue.TryGetValue(out JsonElement? _));

// Bool primitive (JsonValueOfJsonBool): JsonElement? and bool? should work
JsonValue boolValue = JsonSerializer.Deserialize<JsonValue>("true");
Assert.True(boolValue.TryGetValue(out JsonElement? _));
Assert.True(boolValue.TryGetValue(out bool? _));

// Number primitive (JsonValueOfJsonNumber): JsonElement? and numeric nullable types should work
JsonValue numberValue = JsonSerializer.Deserialize<JsonValue>("42");
Assert.True(numberValue.TryGetValue(out JsonElement? _));
Assert.True(numberValue.TryGetValue(out int? _));
Assert.True(numberValue.TryGetValue(out long? _));
Assert.True(numberValue.TryGetValue(out double? _));
Assert.True(numberValue.TryGetValue(out short? _));
Assert.True(numberValue.TryGetValue(out decimal? _));
Assert.True(numberValue.TryGetValue(out byte? _));
Assert.True(numberValue.TryGetValue(out float? _));
Assert.True(numberValue.TryGetValue(out uint? _));
Assert.True(numberValue.TryGetValue(out ushort? _));
Assert.True(numberValue.TryGetValue(out ulong? _));
Assert.True(numberValue.TryGetValue(out sbyte? _));
}

[Theory]
[InlineData("\"A\"")]
[InlineData("\" \"")]
Expand Down