Description
Background and motivation
System.Text.Json constructor-based deserialization currently treats all constructor parameters as optional, as can be highlighted in the following example:
var result = JsonSerializer.Deserialize<Person>("{}");
Console.WriteLine(result); // Person { Name = , Age = 0 }
public record Person(string Name, int Age);
This can create unexpected validation problems since users typically think of non-optional parameters as required values in the object contract. It typically also results in deserialized properties violating their own nullability annotations. Another problem is that it could result either in discrepancies or overly verbose outputs in components that are attempting to derive a JSON schema from the STJ contracts.
Changing this behavior would most likely constitute a serious breaking change, so we would instead like to expose a feature flag that opts in to new behavior, marking non-optional constructor parameters as required. Rather than making this an application-wide feature switch, this should instead be a per-JsonSerializerOptions
setting to avoid breaking third-party components making use of STJ.
Related to #1256
API Proposal
namespace System.Text.Json;
public partial class JsonSerializerOptions
{
public bool RequireConstructorParameters { get; set; } = false;
}
namespace System.Text.Json.Serialization;
public partial class JsonSourceGenerationOptionsAttribute
{
public bool RequireConstructorParameters { get; set; } = false;
}
API Usage
var options = new JsonSerializerOptions { RequireNonOptionalConstructorParameters = true };
JsonSerializer.Deserialize<Person>("""{"Name" : "John", "Age" : 27 }""", options); // Success
JsonSerializer.Deserialize<Person>("""{"Name" : "John", "Address" : "known"}""", options);
// JSON deserialization for type 'Person' was missing required properties, including the following: Age
public record Person(string Name, int Age, string Address = "unknown");
Alternative Designs
This proposal is very closely related to #100144. We should consider a design that unifies both behaviors under a single feature switch.
Risks
No response