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

JsonSerializerOptions copy constructor should include the metadata resolver #71716

Closed
eiriktsarpalis opened this issue Jul 6, 2022 · 2 comments · Fixed by #71746
Closed

JsonSerializerOptions copy constructor should include the metadata resolver #71716

eiriktsarpalis opened this issue Jul 6, 2022 · 2 comments · Fixed by #71746
Assignees
Labels
area-System.Text.Json breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet
Milestone

Comments

@eiriktsarpalis
Copy link
Member

With the release of source generation in .NET 6 the JsonSerializerOptions copy constructor was intentionally made to ignore its JsonSerializerContext state (see also dotnet/aspnetcore#38720). This made sense at the time since JsonSerializerContext was designed to have a 1:1 relationship with JsonSerializerOptions instances.

The implementation of #63686 generalizes JsonSerializerContext with IJsonTypeInfoResolver, which can be used to generate metadata for parametric JsonSerializerOptions instances. The JsonSerializerContext type and source generator have been retrofitted and now implement IJsonTypeInfoResolver.

This issue proposes that we change the JsonSerializerOptions copy constructor so that it also incorporates the metadata resolver. This can potentially introduce a breaking change for users, for instance:

var options = new JsonSerializerOptions(MyContext.Default.Options);
JsonSerializer.Serialize(new Poco1(), options); // will fail serialization since the cloned options instance preserves `MyContext.Default` as its metadata resolver

[JsonSerializable(typeof(Poco1))]
public partial class MyContext : JsonSerializerContext {}

public class Poco1 {}
public class Poco2 {}

For impacted users the suggested workaround is the following:

var options = new JsonSerializerOptions(MyContext.Default.Options);
options.TypeInfoResolver = null; // unset the `MyContext.Default` as the resolver for the options instance.
@eiriktsarpalis eiriktsarpalis self-assigned this Jul 6, 2022
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jul 6, 2022
@eiriktsarpalis eiriktsarpalis added breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. and removed area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Jul 6, 2022
@ghost
Copy link

ghost commented Jul 6, 2022

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

Issue Details

With the release of source generation in .NET 6 the JsonSerializerOptions copy constructor was intentionally made to ignore its JsonSerializerContext state (see also dotnet/aspnetcore#38720). This made sense at the time since JsonSerializerContext was designed to have a 1:1 relationship with JsonSerializerOptions instances.

The implementation of #63686 generalizes JsonSerializerContext with IJsonTypeInfoResolver, which can be used to generate metadata for parametric JsonSerializerOptions instances. The JsonSerializerContext type and source generator have been retrofitted and now implement IJsonTypeInfoResolver.

This issue proposes that we change the JsonSerializerOptions copy constructor so that it also incorporates the metadata resolver. This can potentially introduce a breaking change for users, for instance:

var options = new JsonSerializerOptions(MyContext.Default.Options);
JsonSerializer.Serialize(new Poco1(), options); // will fail serialization since the cloned options instance preserves `MyContext.Default` as its metadata resolver

[JsonSerializable(typeof(Poco1))]
public partial class MyContext : JsonSerializerContext {}

public class Poco1 {}
public class Poco2 {}

For impacted users the suggested workaround is the following:

var options = new JsonSerializerOptions(MyContext.Default.Options);
options.TypeInfoResolver = null; // unset the `MyContext.Default` as the resolver for the options instance.
Author: eiriktsarpalis
Assignees: eiriktsarpalis
Labels:

area-System.Text.Json

Milestone: -

@eiriktsarpalis eiriktsarpalis added this to the 7.0.0 milestone Jul 6, 2022
@eiriktsarpalis eiriktsarpalis added area-System.Text.Json needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet labels Jul 6, 2022
@ghost
Copy link

ghost commented Jul 6, 2022

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

Issue Details

With the release of source generation in .NET 6 the JsonSerializerOptions copy constructor was intentionally made to ignore its JsonSerializerContext state (see also dotnet/aspnetcore#38720). This made sense at the time since JsonSerializerContext was designed to have a 1:1 relationship with JsonSerializerOptions instances.

The implementation of #63686 generalizes JsonSerializerContext with IJsonTypeInfoResolver, which can be used to generate metadata for parametric JsonSerializerOptions instances. The JsonSerializerContext type and source generator have been retrofitted and now implement IJsonTypeInfoResolver.

This issue proposes that we change the JsonSerializerOptions copy constructor so that it also incorporates the metadata resolver. This can potentially introduce a breaking change for users, for instance:

var options = new JsonSerializerOptions(MyContext.Default.Options);
JsonSerializer.Serialize(new Poco1(), options); // will fail serialization since the cloned options instance preserves `MyContext.Default` as its metadata resolver

[JsonSerializable(typeof(Poco1))]
public partial class MyContext : JsonSerializerContext {}

public class Poco1 {}
public class Poco2 {}

For impacted users the suggested workaround is the following:

var options = new JsonSerializerOptions(MyContext.Default.Options);
options.TypeInfoResolver = null; // unset the `MyContext.Default` as the resolver for the options instance.
Author: eiriktsarpalis
Assignees: eiriktsarpalis
Labels:

area-System.Text.Json, breaking-change

Milestone: 7.0.0

eiriktsarpalis added a commit to eiriktsarpalis/runtime that referenced this issue Jul 7, 2022
…t#71714

Include JsonSerializerContext in JsonSerializerOptions copy constructor. Fix dotnet#71716

Move reflection-based converter resolution out of JsonSerializerOptions. Fix dotnet#68878
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jul 7, 2022
eiriktsarpalis added a commit that referenced this issue Jul 7, 2022
* Remove implicit fallback to reflection-based serialization. Fix #71714

Include JsonSerializerContext in JsonSerializerOptions copy constructor. Fix #71716

Move reflection-based converter resolution out of JsonSerializerOptions. Fix #68878

* Address feedback & add one more test

* Update src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* fix build

* Bring back throwing behavior in JsonSerializerContext and add tests

* Only create caching contexts if a resolver is populated

* Add null test for JsonSerializerContext interface implementation.

* skip RemoteExecutor test in netfx targets

* Add DefaultJsonTypeInfoResolver test for types with JsonConverterAttribute

* remove nullability annotation

* Update src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs

Co-authored-by: Krzysztof Wicher <mordotymoja@gmail.com>

Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: Krzysztof Wicher <mordotymoja@gmail.com>
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jul 7, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Aug 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant