dotnet / dotnet/runtime

JsonObjectCreationHandling.Populate does not work with custom converters

Open
#122,000 4 comments 0 reactions 0 assignees View on GitHub
area-System.Text.Json
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

In .NET 8, JsonObjectCreationHandling.Populate is a really useful feature.

However, it currently does not work when a custom JsonConverter is applied. If a property uses a converter, the existing instance is ignored, and Populate doesn’t happen. This is frustrating because in many real-world scenarios, you want to both:
- Use a property wrapper or immutable object with Populate
- Use a custom converter for special serialization logic

Example Scenario:

```csharp
public class Wrapper
{
public int Value { get; set; }
}

public class MyClass
{
public Wrapper MyProperty { get; } = new Wrapper();
}

public class WrapperConverter : JsonConverter
{
public override Wrapper Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Custom deserialization logic
return new Wrapper { Value = reader.GetInt32() }; // Always creates a new instance
}

public override void Write(Utf8JsonWriter writer, Wrapper value, JsonSerializerOptions options)
{
writer.WriteNumberValue(value.Value);
}
}

// Usage
var obj = new MyClass();
JsonSerializer.Deserialize(json, new JsonSerializerOptions
{
PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate,
Converters = { new WrapperConverter() }
});

// `MyProperty` is replaced, Populate is ignored

```

Why This Is Painful:
- Breaks the expectation of Populate, you can’t combine it with custom converters.
- Forces workarounds like deserializing to a temporary object and manually merging, which is verbose and error-prone.
- Makes it harder to use Populate in real-world apps that rely on converters for complex types.

Feature Request / Suggestion:
- Allow JsonObjectCreationHandling.Populate to work even when a custom converter is applied.
- Ideally, the existing instance could be passed to Read(), or there could be a supported way for converters to populate objects in place.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.