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

JsonIgnore attribute has no effect on init-only properties in source generation mode #101877

Open
trympet opened this issue May 4, 2024 · 2 comments
Labels
area-System.Text.Json bug source-generator Indicates an issue with a source generator feature
Milestone

Comments

@trympet
Copy link
Contributor

trympet commented May 4, 2024

Description

The JsonIgnore attribute is ignored for init-only properties in source generation mode.

A motivating example is when I have an outer record wrapping some inner record to perform some serialization transformation.

record MyRecord([property: JsonIgnore] MyOtherRecord MyOtherRecord)
{
    [JsonConstructor]
    public MyRecord(int foo) : this(new MyOtherRecord(foo, "Baz"))
    {
    }

    [JsonPropertyName("foo")] public string Foo => MyOtherRecord.Foo.ToString();
}

record MyOtherRecord(int Foo, string Bar);

[JsonSerializable(typeof(MyRecord))]
partial class JsonContext : JsonSerializerContext;

In the example above, the object initializer for MyRecord, generated by the json source generation machinery, would override the initialized value of the MyOtherRecord property to null -- despite having a JsonIgnore applied to the property.

Reproduction Steps

Apply the JsonIgnore attribute to an init-only property and observe that the init is invoked upon object construction. As illustrated below, the behavior seems to diverge from reflection mode.

var reflection = JsonSerializer.Deserialize<JsonClass>("""{"A":1}""");
Console.WriteLine($"Property: {reflection!.Property}"); // Property: 42

var sourceGenerated = JsonSerializer.Deserialize<JsonClass>("""{"A":1}""", JsonContext.Default.JsonClass);
Console.WriteLine($"Property: {sourceGenerated!.Property}"); // Property: 0

class JsonClass
{
    [JsonIgnore(Condition = JsonIgnoreCondition.Always)]
    public int Property { get; init; } = 42;
}

[JsonSerializable(typeof(JsonClass))]
partial class JsonContext : JsonSerializerContext;

Expected behavior

The JsonIgnore attribute should, when applied to an init-only property, cause the property initializer to be omitted entirely from object construction.

From the docs:

[JsonIgnore] Prevents a property or field from being serialized or deserialized.

Actual behavior

The init-only property is effectively behaving as if the ignore condition is set to JsonIgnoreCondition.Never, thus causing any value set in the constructor to subsequently be overridden.

Regression?

No response

Known Workarounds

Changing the accessor from init to set updates ObjectWithParameterizedConstructorCreator from static args => new global::JsonClass(){ Property = (int)args[0] } to static args => new global::JsonClass().

Configuration

.NET 8
SDK 8.0.204

Other information

No response

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label May 4, 2024
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.

@eiriktsarpalis eiriktsarpalis added bug source-generator Indicates an issue with a source generator feature and removed untriaged New issue has not been triaged by the area owner labels May 9, 2024
@eiriktsarpalis eiriktsarpalis added this to the Future milestone May 9, 2024
@eiriktsarpalis
Copy link
Member

Thanks for reporting, this looks like a source generator bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Text.Json bug source-generator Indicates an issue with a source generator feature
Projects
None yet
Development

No branches or pull requests

2 participants