I have a object structure like List<Dictionary<string, int>>
and I serialize it directly with JsonSerializer
. Obviously I can't use it as it is for AOT or I get:
JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.
Now I know how it is typically done when using your own custom types, but what are my options for built-in?
You set up JSON source generation for system types TSystem
in exactly the same way you do for custom types: define some JsonSerializerContext
with [JsonSerializable(typeof(TSystem))]
applied:
[JsonSourceGenerationOptions(WriteIndented = true)] // Add whatever options you want here.
[JsonSerializable(typeof(List<Dictionary<string, int>>))]
// Add additional [JsonSerializable(typeof(T))] attributes as required.
public partial class MySerializationContext : JsonSerializerContext;
The only question is, what JsonTypeInfo<TSystem>
property name will be generated for MySerializationContext
for a generic system type like List<Dictionary<string, int>>
? As it turns out, it's formed by concatenating all the type names in order, i.e. ListDictionaryStringInt32
:
List<Dictionary<string, int>> list = new()
{
new() { {"foo", 10}, {"bar", 20}, }
};
var json = JsonSerializer.Serialize(
list,
MySerializationContext.Default.ListDictionaryStringInt32);
If you're not sure, you can instead call JsonSerializerContext.GetTypeInfo(Type)
to get the required type info in runtime:
var typeInfo = (JsonTypeInfo<List<Dictionary<string, int>>>?)MySerializationContext.Default.GetTypeInfo(list.GetType());
if (typeInfo == null)
throw new JsonException($"TypeInfo not found for {list.GetType()}");
var json = JsonSerializer.Serialize(list, typeInfo);
You can also determine the property name by using reflection in the debugger:
Console.WriteLine(string.Join(",", MySerializationContext.Default.GetType().GetProperties().Select(p => p.Name)));