Search code examples
c#.netsystem.text.json.net-6.0sourcegenerators

Use System.Text.Json source generator with custom JsonConverter


How are custom JsonConverter<> classes used together with System.Text.Json source generator?

I would like to call JsonSerializer.Deserialize<MyType[]>() that doesn't fallback to a reflection-based implementation and uses a custom MyTypeJsonParser : JsonConverter<MyType>.

EDIT to clarify: Custom converter is implemented for MyType, but json contains an array of MyType objects. So, I would like to create source generated JsonSerializerContext that deserializes an array of MyType objects (MyType[]), using generated code to deserialize an array part and manual converter to deserialize a MyType objects part.

Old code (that doesn't use a source generator) applies a custom converter, by adding it to JsonSerializerOptions.Converters.

However, upon further research I found out that Converters property is missing in JsonSourceGenerationOptionsAttribute. The tables in documentation also state that JsonConverterAttribute and JsonSerializerOptions.Converters are not supported in serialization optimization mode. So, it seems that mixing of custom converters with json source generator is currently (.NET 6) not possible.

The documentation is not clear, whether at least metadata collection source generation mode can use JsonConverterAttribute.


Solution

  • According to the documentation you can create a JsonSerializerOptions, add your converter and use it in the serialization.

    var options = new JsonSerializerOptions
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        WriteIndented = false,
    };
    options.Converters.Add(new MyConverter());
    
    var myJsonSerializerContext = new MyJsonSerializerContext(options);
    

    You cant share your JsonSerializerOptions with several SerializerContext, another thing it was not clear to me reading the documentation is that you can have one SerializerContext for n types.

    So you can have one SerializerContext for all your types initialize and cache it so you can reuse it to avoid allocating more memory.