-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
S.T.J.JsonSerializer doesn't support properties marked with JsonRequiredAttribute that're initialized through ctor #78098
Comments
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsDescription
Reproduction Stepsusing System.Text.Json.Serialization;
namespace Test;
internal static class JsonRequired
{
public sealed class RequiredAttributeCtor
{
[JsonPropertyName("value")]
[JsonRequired]
public int Value { get; }
public RequiredAttributeCtor(int value)
{
Value = value;
}
}
public static RequiredAttributeCtor? Run()
{
const string input = """{"value":1}""";
return System.Text.Json.JsonSerializer.Deserialize<RequiredAttributeCtor>(input);
}
} Expected behaviorLocalReproduction test returns instance of RequiredAttributeCtor type populated with data from input GlobalAll of the required property initialization variations are supported using System.Text.Json.Serialization;
namespace Test;
internal static class JsonRequired
{
public sealed class RequiredAttributeCtor
{
[JsonPropertyName("value")]
[JsonRequired]
public int Value { get; }
public RequiredAttributeCtor(int value)
{
Value = value;
}
}
public sealed class RequiredAttributeSet
{
[JsonPropertyName("value")]
[JsonRequired]
public int Value { get; set; }
}
public sealed class RequiredAttributeInit
{
[JsonPropertyName("value")]
[JsonRequired]
public int Value { get; init; }
}
public sealed class RequiredKeywordSet
{
[JsonPropertyName("value")]
public required int Value { get; set; }
}
public sealed class RequiredKeywordInit
{
[JsonPropertyName("value")]
public required int Value { get; init; }
}
public static void Run()
{
const string input = """{"value":1}""";
var _1 = System.Text.Json.JsonSerializer.Deserialize<RequiredAttributeCtor>(input);
var _2 = System.Text.Json.JsonSerializer.Deserialize<RequiredAttributeSet>(input);
var _3 = System.Text.Json.JsonSerializer.Deserialize<RequiredAttributeInit>(input);
var _4 = System.Text.Json.JsonSerializer.Deserialize<RequiredKeywordSet>(input);
var _5 = System.Text.Json.JsonSerializer.Deserialize<RequiredKeywordInit>(input);
}
} Actual behaviorRunning reproduction test throws
Regression?No response Known WorkaroundsNo response ConfigurationSDK version: 7.0.100 Other informationIt seems like implementation of required keyword support in #72937
|
Only scenario |
@SicJG thanks for the report on this, I've sent a PR with a fix. Once it's merged you should be able to consume nightly NuGet package with a fix some time after that. I'll check if it qualifies for servicing fix for 7.0 but no promises on that. |
I don't believe this meets the bar for a 7.0 fix. public class MyPoco
{
public MyPoco(int value) => Value = value;
public required int Value { get; }
} That being said, we should make sure that |
Unfortunately, this is a blocker for us to use the |
@MartyIX the isolated fix is in the PR #78152. There is also workaround which I didn't mention yet: using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
JsonSerializerOptions options = new()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers = { JsonRequiredWithPropertiesWithoutSetter }
}
};
MyPoco obj = JsonSerializer.Deserialize<MyPoco>("""{"Value": 123}""", options);
Console.WriteLine(obj.Value);
void JsonRequiredWithPropertiesWithoutSetter(JsonTypeInfo typeInfo)
{
if (typeInfo.Kind != JsonTypeInfoKind.Object)
return;
foreach (var property in typeInfo.Properties)
{
if (property.IsRequired && property.Set == null)
{
// this will never be called for parameterized constructors
property.Set = (obj, val) => throw new JsonException("Required property doesn't have setter");
}
}
}
public class MyPoco
{
public MyPoco(int value) => Value = value;
[JsonRequired]
public int Value { get; }
} |
Moving to 9.0 per #78152 (comment) |
Might be considered as closed due to implementation of JsonSerializerOptions.RespectRequiredConstructorParameters as well as JsonSerializerOptions.RespectNullableAnnotations |
It seems we might still want to make this work if the flag hasn't been enabled though. Let's leave this open for now. |
Description
Reproduction Steps
Expected behavior
Local
Reproduction test returns instance of RequiredAttributeCtor type populated with data from input
Global
All of the required property initialization variations are supported
Actual behavior
Running reproduction test throws
Regression?
No response
Known Workarounds
No response
Configuration
SDK version: 7.0.100
OS: Windows 10 1909
Arch: x64
Other information
It seems like implementation of required keyword support in #72937
was made in way that makes JsonRequiredAttribute usage absolutely simular to new "required" keyword usage, missing the fact that validating absence of input json property using attribute might be used in other scenarios.
The text was updated successfully, but these errors were encountered: