dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.27k stars 4.73k forks source link

Support for custom metadata in JsonConverters #444

Closed Danielku15 closed 4 years ago

Danielku15 commented 4 years ago

Summary I have the need for my custom JsonConverter(Factory) implementations to pass on some metadata/custom-context along the serialization. Currently it is not possible to "inject" context related information from outside or from within a JsonConverter.

It would be great if there would be a JsonSerializationContext which contains beside the existing JsonSerializerOptions a container for custom items like IDictionary<string, object> CustomItems {get;}. This container can be used to pass on options for the JsonConverters.

More Background I am currently developing a small framework which customizes the serialized JSON in case the objects were contained in a wrapper. Lets name it: ApiResponse<T> which contains a T[] Items {get; set;}. I made a custom JsonConverter(Factory) which takes over the serialization process of this class. Additionally I have some metadata which properties of the objects actually need to be serialized. While the serializer logic/implementation is always the same, I need to be able to pass on the container which properties of the graph should be serialized.

My JsonConverter might fill additional values into the CustomItems or read some from there. I cannot store easily this information somewhere on JsonConverter level as it is specific to the actual serialization call and callstack.

Use cases

I think it might be a bit a corner case what I am trying to achive, but I can imagine that also others who make some customized JsonConverters need to pass on some options that are specific per serialization call.

Known Workaround

I can currently "clone" the default JsonSerializerOptions and inject a custom newly created JsonConverter which keeps the settings as member. When calling in nested fashion, I again need to clone the options and inject a special sub JsonConverter instance. But this has a terrible performance impact as the JsonSerializerOptions keeps the type metadata for serialization.

layomia commented 4 years ago

This scenario looks like it could be resolved with app logic using ThreadLocal<T>, AsyncLocal<T>, or add properties to you converter and manually flow them. In the future, we could make JsonSerializerOptions non-sealed and add some state that could be useful.