Skip to content

Bugfix/113926 fix invalid jsonnode deserialization #114863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Maximys
Copy link
Contributor

@Maximys Maximys commented Apr 21, 2025

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Apr 21, 2025
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.


namespace System.Text.Json.Nodes
namespace System.Text.Json.Nodes.Generics
Copy link
Member

Choose a reason for hiding this comment

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

Please avoid including large refactor without first discussing with the owners. It can have many unintentional effects.


namespace System.Text.Json.Serialization.Converters.Node.Generics
{
internal sealed class JsonValuePrimitiveBooleanConverter : JsonValuePrimitiveConverter<bool>
Copy link
Member

Choose a reason for hiding this comment

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

It's not efficient to create dedicated converter class for each generic instantiation.

Instead, create a converter factory for Generic<T>, and invokes the converter of T. Check how NullableConverter, FSharpOptionConverter and JsonCollectionConverter invokes JsonConverter<TElement>.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought the performance of this approach was better

Copy link
Member

Choose a reason for hiding this comment

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

While it may improve performance to inline one level of virtual call, it can be easily compensated by other stuff like the ConcurrentDictionary lookup. It's way not maintainable.

Copy link
Member

@huoyaoyuan huoyaoyuan Apr 23, 2025

Choose a reason for hiding this comment

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

I also noticed a behavioral discrepancy. If the caller specifies a converter for primitive type, it will be respected by the "container" converters (collections/nullable), but not JsonObject. Even if we decide to keep this behavior, it should be achieved in generic way, by acquiring corresponding JsonPrimitiveConverter<T>.

I'd suggest to hold off and let the area owner make a decision on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, and this code already removed

@@ -1417,5 +1420,311 @@ internal bool TryGetGuidCore(out Guid value)
value = default;
return false;
}

internal char GetChar()
Copy link
Member

Choose a reason for hiding this comment

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

These changes can be reverted once you are invoking the corresponding JsonConverter<Primitive>.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed by force push 9047de2

@@ -16,9 +19,12 @@ internal sealed class JsonNodeConverter : JsonConverter<JsonNode?>
{
private static JsonNodeConverter? s_nodeConverter;
private static JsonArrayConverter? s_arrayConverter;
private static ConcurrentDictionary<Type, JsonConverter>? s_jsonValuePrimitiveConverters;
Copy link
Member

Choose a reason for hiding this comment

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

Do not store converters like this. Use a converter factory to create converter for each JsonValuePrimitive<T>. Check NullableConverterFactory.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Fixed by force push 9047de2

@Maximys Maximys force-pushed the bugfix/113926-fix-invalid-jsonnode-deserialization branch from cf9d968 to 9047de2 Compare April 23, 2025 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Text.Json community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deserialization of a JsonNode with string value fails
2 participants