我正在尝试为
Optional
包装类实现 JSON 序列化。我希望序列化类似于可为 null 的类型,所以:
"myOptional": null
对于空,并且
"myOptional": 2
或
"myOptional": { . . . }
对于物体。
这很好,直到我到达一个包装的对象,我不知道如何告诉序列化器“像平常一样序列化这个对象”。微软文档让我相信我必须实现
JsonConverterFactory
,但我不知道如何告诉作者自动序列化内部对象。
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.
}
}
}
}
我应该如何实现这一目标? 举个例子,如果
Optional<T>
有 T = MyClass
并且 MyClass
是
{
public int ID { get; set; } = 2
public string Name { get; set; } = "myname"
}
然后我希望将其序列化为
"optionalofMyClass":
{
"ID": 2,
"Name": "myname"
}
如果我理解你的问题,你想序列化你的对象,无论它是否有值。如果它没有值,它应该显示为 null,当它有值时,它应该显示为嵌套的 json 结构。我尝试使用下面的代码
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
public class Program
{
public static void Main()
{
Person p1 = new Person {Id = 1, Name = "User1"};
var output1 = new Wrapper<Person>(p1);
Console.WriteLine(JsonSerializer.Serialize(output1));
Person p2 = new Person();
var output2 = new Wrapper<Person>(p2);
Console.WriteLine(JsonSerializer.Serialize(output2));
Person p3 = null;
var output3 = new Wrapper<Person>(p3);
Console.WriteLine(JsonSerializer.Serialize(output3));
}
}
public class Wrapper<T> where T : class {
public T optionalOfMyClass { get; set; }
public Wrapper(T data) {
optionalOfMyClass = data;
}
}
public class Person {
public int Id { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Name { get; set; }
}