vendredi 13 octobre 2023

C# Serialize Generic Wrapper class

I'm trying to implement JSON serialization for an Optional wrapper class. I want the serialization to be akin to a nullable type, so:

"myOptional": null

for null, and

"myOptional": 2

or

"myOptional": { . . . }

for objects.

This is fine until I get to a wrapped object, I don't know how to tell the serializer to "serialize this object like you normally would". The Microsoft docs lead me to believe that I have to implement JsonConverterFactory, but I don't know how to tell the writer to serialize the inner object automatically.

public class OptionalTypeJsonConverterFactory : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert)
    {
        return typeToConvert
            .GetGenericArguments()[0].IsClass;
    }

    public override JsonConverter CreateConverter(
        Type type,
        JsonSerializerOptions options
    )
    {
        return (JsonConverter)Activator.CreateInstance(
            type: typeof(OptionalJsonConverter<>).MakeGenericType(type.GenericTypeArguments[0]),
            bindingAttr: BindingFlags.Instance | BindingFlags.Public,
            binder: null,
            args: new object[] { options },
            culture: null
        )!;
    }

    private class OptionalJsonConverter<T> : JsonConverter<Optional<T>>
        where T : struct
    {
        public OptionalJsonConverter(JsonSerializerOptions options) { }

        public override Optional<T>? Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options
        )
        {
            throw new NotImplementedException();
        }

        public override void Write(
            Utf8JsonWriter writer,
            Optional<T> optional,
            JsonSerializerOptions options
        )
        {
            if (optional.IsNone())
            {
                writer.WriteNullValue();
            }
            else
            {
                // don't know what to put here. I want to serialize objects as if the wrapper was never there.
            }
        }
    }
}

How should I go about achieving this? As an example, if Optional<T> has T = MyClass and MyClass is

{
  public int ID { get; set; } = 2
  public string Name { get; set; } = "myname"
}

then I want this to serialize to

"optionalofMyClass": 
{
  "ID": 2,
  "Name": "myname"
}




Aucun commentaire:

Enregistrer un commentaire