我不明白为什么下面的代码在
StackOverflowException
期间抛出 Write
。我希望能够使用类型鉴别器来帮助我序列化/反序列化对象,同时不丢失具体的实现细节。我该如何解决这个问题?
using System.Text.Json;
using System.Text.Json.Serialization;
public abstract class ClassC
{
public string PropertyC { get; set; }
public string TypeDiscriminator => this.GetType().FullName;
}
public class ClassB : ClassC
{
public string PropertyB { get; set; }
}
public class ClassA : ClassB
{
public string PropertyA { get; set; }
}
public class PolymorphicJsonConverter<TBase> : JsonConverter<TBase> where TBase : ClassC
{
public override bool CanConvert(Type typeToConvert) => typeof(TBase).IsAssignableFrom(typeToConvert);
public override TBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
var root = jsonDoc.RootElement;
var typeDiscriminator = root.GetProperty("TypeDiscriminator").GetString();
var type = Type.GetType(typeDiscriminator);
if (type == null)
{
throw new JsonException($"Type {typeDiscriminator} could not be found.");
}
return (TBase)JsonSerializer.Deserialize(root.GetRawText(), type, options);
}
}
public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
public class Program
{
public static void Main()
{
var options = new JsonSerializerOptions
{
Converters = { new PolymorphicJsonConverter<ClassC>() },
WriteIndented = true
};
ClassA classA = new ClassA { PropertyA = "ValueA", PropertyB = "ValueB", PropertyC = "ValueC" };
string json = JsonSerializer.Serialize<ClassC>(classA, options);
ClassC deserialized = JsonSerializer.Deserialize<ClassC>(json, options);
Console.WriteLine(json);
Console.WriteLine(deserialized is ClassA); // Should output 'True'
}
}
在您的
Write
方法中,您再次调用您的 Write
方法 - 您有一个循环 - 一段时间后,您的应用程序内存不足。在 Write
方法中打个断点看看。
您应该在
writer
方法中使用 Write
。这是文档中的基本转换器示例:
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class DateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset>
{
public override DateTimeOffset Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
DateTimeOffset.ParseExact(reader.GetString()!,
"MM/dd/yyyy", CultureInfo.InvariantCulture);
public override void Write(
Utf8JsonWriter writer,
DateTimeOffset dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue.ToString(
"MM/dd/yyyy", CultureInfo.InvariantCulture));
}
}