Skip to content
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

STJ: Support serialization callbacks for collection and dictionary types #104120

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

Conversation

manandre
Copy link
Contributor

Closes #71945

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jun 27, 2024
Comment on lines 280 to +282
value = (TCollection)state.Current.ReturnValue!;

jsonTypeInfo.OnDeserialized?.Invoke(value);
Copy link
Member

@eiriktsarpalis eiriktsarpalis Jun 28, 2024

Choose a reason for hiding this comment

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

If TCollection is a struct this would result in the value being boxed again and potentially breaking user callback that depend on the same reference being passed to the callback.

Suggested change
value = (TCollection)state.Current.ReturnValue!;
jsonTypeInfo.OnDeserialized?.Invoke(value);
object result = state.Current.ReturnValue!;
value = (TCollection)result;
jsonTypeInfo.OnDeserialized?.Invoke(result);

state.Current.JsonPropertyInfo = state.Current.JsonTypeInfo.ElementTypeInfo!.PropertyInfoForTypeInfo;
state.Current.JsonPropertyInfo = jsonTypeInfo.ElementTypeInfo!.PropertyInfoForTypeInfo;

jsonTypeInfo.OnSerializing?.Invoke(value);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I would move the callback before the first JSON gets written to the underlying writer.

Comment on lines 308 to +310
value = (TDictionary)state.Current.ReturnValue!;

jsonTypeInfo.OnDeserialized?.Invoke(value);
Copy link
Member

Choose a reason for hiding this comment

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

Likewise

Suggested change
value = (TDictionary)state.Current.ReturnValue!;
jsonTypeInfo.OnDeserialized?.Invoke(value);
object result = state.Current.ReturnValue!;
value = (TDictionary)result;
jsonTypeInfo.OnDeserialized?.Invoke(result);

state.Current.JsonPropertyInfo = state.Current.JsonTypeInfo.ElementTypeInfo!.PropertyInfoForTypeInfo;
state.Current.JsonPropertyInfo = jsonTypeInfo.ElementTypeInfo!.PropertyInfoForTypeInfo;

jsonTypeInfo.OnSerializing?.Invoke(dictionary);
Copy link
Member

Choose a reason for hiding this comment

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

Likewise, I would invoke the callback before metadata or the start object token get written to the wire.

@@ -153,7 +153,7 @@ internal JsonTypeInfo(Type type, JsonConverter converter, JsonSerializerOptions
{
VerifyMutable();

if (Kind != JsonTypeInfoKind.Object)
if (Kind == JsonTypeInfoKind.None)
Copy link
Member

Choose a reason for hiding this comment

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

In the unlikely case that new kinds get added in the future, I would probably just turn this into an explicit check:

Suggested change
if (Kind == JsonTypeInfoKind.None)
if (Kind is not (JsonTypeInfoKind.Object or JsonTypeInfoKind.Enumerable or JsonTypeInfoKind.Dictionary))

@@ -419,10 +531,7 @@ public override void Write(Utf8JsonWriter writer, MyValue value, JsonSerializerO
[Fact]
public static void NonPocosIgnored()
{
JsonSerializer.Serialize(new MyCollection());
Copy link
Member

Choose a reason for hiding this comment

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

Could you also add a few tests in MetadataTests.cs that verify that callbacks can be specified via the JsonTypeInfo APIs?

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.

System.Text.Json serialization callbacks not supported by collection types
2 participants