Description
Description
When using System.Text json source generation mode, the JsonObjectCreationHandling.Populate option does not work correctly when having a required init property in the class.
Reproduction Steps
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
public class Program
{
public static void Main()
{
var json = """{ "Text": {"Value": "Hello" }, "Values": [4, 5, 6] }""";
// Deserialization using source generation
Console.WriteLine("Deserialization using source generation");
var working = JsonSerializer.Deserialize(json, GetterOnlyContext.Default.GetterOnly);
Console.WriteLine(working); // Hello 1, 2, 3, 4, 5, 6
var notWorking = JsonSerializer.Deserialize(json, RequiredInitContext.Default.RequiredInit);
Console.WriteLine(notWorking); // Hello 1, 2, 3
// Deserialization using options
Console.WriteLine("Deserialization using options");
var options = new JsonSerializerOptions { PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate };
var working2 = JsonSerializer.Deserialize<GetterOnly>(json, options);
Console.WriteLine(working2); // Hello 1, 2, 3, 4, 5, 6
var working3 = JsonSerializer.Deserialize<RequiredInit>(json, options);
Console.WriteLine(working3); // Hello 1, 2, 3, 4, 5, 6
}
}
public class Text {
public required string Value { get; set; }
}
public class GetterOnly
{
public Text Text { get; } = new() { Value = "Default" };
public IList<int> Values { get; } = [1, 2, 3];
public override string ToString() => $"{Text.Value} {string.Join(", ", Values)}";
}
public class RequiredInit
{
public required Text Text { get; init; }
public IList<int> Values { get; } = [1, 2, 3];
public override string ToString() => $"{Text.Value} {string.Join(", ", Values)}";
}
[JsonSourceGenerationOptions(
PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate
)]
[JsonSerializable(typeof(GetterOnly))]
public partial class GetterOnlyContext : JsonSerializerContext { }
[JsonSourceGenerationOptions(
PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate
)]
[JsonSerializable(typeof(RequiredInit))]
public partial class RequiredInitContext : JsonSerializerContext { }
Expected behavior
The Values
from the json payload are appended to the existing IList<int> Values
in all cases.
Actual behavior
Running the code snippet does not generate an runtime error, but does not append [4, 5, 6]
in the notWorking
-Variable case. Output:
Deserialization using source generation
Hello 1, 2, 3, 4, 5, 6
Hello 1, 2, 3
Deserialization using options
Hello 1, 2, 3, 4, 5, 6
Hello 1, 2, 3, 4, 5, 6
Regression?
No response
Known Workarounds
No response
Configuration
.NET SDK:
Version: 9.0.103
Commit: 96da45d427
Workload version: 9.0.100-manifests.ea610b94
MSBuild version: 17.12.24+90b52dda6
Laufzeitumgebung:
OS Name: Windows
OS Version: 10.0.26100
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.103\
Installierte .NET-Workloads:
Es sind keine installierten Workloads zum Anzeigen vorhanden.
Konfiguriert für die Verwendung loose manifests beim Installieren neuer Manifeste.
Host:
Version: 9.0.2
Architecture: x64
Commit: 80aa709
.NET SDKs installed:
9.0.102 [C:\Program Files\dotnet\sdk]
9.0.103 [C:\Program Files\dotnet\sdk]
Other information
No response