6

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.

zigzag
  • 579
  • 5
  • 17
  • Could you clarify a little? How are you applying the converter? 1) Via `[JsonConverter(typeof(MyTypeJsonParser))]` on a property? 2) `[JsonConverter(typeof(MyTypeJsonParser))]` on `MyType` itself? 3) By adding it to `JsonSerializerOptions.Converters`? Also, converters are used to manually serialize and deserialize a type, so how would you use a converter *together with* source generation for automatic serialization? – dbc Dec 17 '21 at 16:03
  • I'm using option #3 (adding it to ```JsonSerializerOptions.Converters)```. Custom converter is only for ```MyType```, but json contains array of ```MyType``` objects (so source generation would be used for array deserialization and converter for deserialization of MyType objects). Option #2 together with ```JsonSerializable(typeof(MyType[]))``` should work I think. – zigzag Dec 17 '21 at 20:12
  • I edited the question to provide more details. Option #2 won't work either. It seems custom converters are not supported together with source generation, which is strange since a custom converter already contains (de)serialization code. – zigzag Dec 18 '21 at 08:59
  • 1
    According to this https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation?pivots=dotnet-6-0#specify-options-by-using-jsonserializeroptions you can create a JsonSerializerOptions, add your converter and then use jsonSerializer.Serialize( myType, typeof(MyType), new MyTypeContext(myJsonSerializerOptions)); – Juan Zamudio Jan 19 '22 at 16:41
  • @JuanZamudio It works. Thank you! Would you care posting it as an answer, so I can mark it as accepted? – zigzag Jan 20 '22 at 09:27

1 Answers1

4

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.

Juan Zamudio
  • 373
  • 11
  • 35