我需要向客户端返回一个包含VMoney类的字段的对象

public class VMoney
{
    public Decimal Value { get; }

    public VMoney(Decimal value)
    {
        Value = value;
    }
}

我继承了班级LimitedVMoney:

public class LimitedVMoney : VMoney
{
    public DateTime? BeginDateTime { get; }
    public DateTime? EndDateTime { get; }

    public LimitedVMoney(Decimal value, DateTime? beginDateTime, DateTime? endDateTime) : base(value)
    {
        if (beginDateTime is null && endDateTime is null) throw new ArgumentException();
        BeginDateTime = beginDateTime;
        EndDateTime = endDateTime;
    }
}

因为当发送到客户端时,可以发送VMoneyLimitedVMoney,所以我创建了VMoneyConverter : JsonConverter<VMoney>

public class VMoneyConverter : JsonConverter<VMoney>
{
    public override VMoney? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using (JsonDocument doc = JsonDocument.ParseValue(ref reader))
        {
            var root = doc.RootElement;
            root.TryGetProperty("beginDateTime", out JsonElement beginDateTimeElement);
            root.TryGetProperty("endDateTime", out JsonElement endDateTimeElement);

            DateTime? beginDateTime = beginDateTimeElement.ValueKind == JsonValueKind.String
                ? beginDateTimeElement.GetDateTime()
                : null;

            DateTime? endDateTime = endDateTimeElement.ValueKind == JsonValueKind.String
                ? endDateTimeElement.GetDateTime()
                : null;

            Decimal value = root.GetProperty("value").GetDecimal();

            return VMoneyFactory.Create(value, beginDateTime, endDateTime);
        }
    }

    public override void Write(Utf8JsonWriter writer, VMoney value, JsonSerializerOptions options)
    {
        if(value is LimitedVMoney limitedVMoney)
        {
            JsonSerializer.Serialize(writer, limitedVMoney, options);
            return;
        }

        JsonSerializer.Serialize(writer, value, options);
    }
}

事实证明,如果类在序列化时是VMoney,那么它将无休止地进入Write方法,之后应用程序将崩溃.

我将解释为什么最初决定编写一个定制的转换器.

如果发送了VMoney,那么它就像应该的那样完美地带有Value字段,但是如果发送了LimitedVMoney,那么它就带有Value字段,但没有BeginDateTime,EndDateTime.

在编写了一个转换器后,结果是,LimitedVMoney与所有字段都是正确的,但VMoney由于循环而不是正确的.

推荐答案

你可以参考官方文件了解how to serialize properties of derived classes with System.Text.Json

var serializeOptions = new JsonSerializerOptions
{
    WriteIndented = true                        
};
   
VMoney limitedVMoney = new LimitedVMoney(100, new DateTime(), new DateTime());
Console.WriteLine(JsonSerializer.Serialize(limitedVMoney,limitedVMoney.GetType(), serializeOptions));
Console.WriteLine(JsonSerializer.Serialize<object>(limitedVMoney, serializeOptions));

如果您必须自定义JsonConverter,您可以修改代码,如下所示:

public override void Write(Utf8JsonWriter writer, VMoney value, JsonSerializerOptions options)
{
     if (value is LimitedVMoney limitedVMoney)
     {
         JsonSerializer.Serialize(writer, limitedVMoney, options);
         return;
     }

     writer.WriteStartObject();

     writer.WriteNumber("Value", value.Value);
     writer.WriteEndObject();
}

Csharp相关问答推荐

发布.NET框架项目将.NET核心元素注入到web. connect中

C# Json重新初始化动态类型

无法使用ternal- .net修复可空警告

程序集.加载从exe的异常

一种安全的方式来存储SSH凭证(MAUI/C#应用程序)

找不到网址:https://localhost:7002/Category/Add?区域= Admin.为什么我的URL是这样生成的?area = Admin而不是/Admin/

为什么总输出就像12.3没有一分一样?

如何删除文件的基础上嵌入的时间戳嵌入文件名

Thad.Sept()vs Task.Delay().Wait()

UWP中的任务和界面

UWP应用程序try 将打包的本机.exe文件加载为C#程序集

在两个已具有一对多关系的表之间添加另一个一对多关系

用于ASP.NET核心的最小扩展坞

EF Core 7-忽略模型绑定中的虚拟属性

在.NET Maui中,Flyoutindow/Hamburger菜单可以在shell 之外实现吗?

如何在C# WinForm控件中使用Windows 10/11的黑暗主题?

C#-如何将int引用获取到byte[]

最小API定义的Swagger标头参数

使用ITfoxtec.Identity.Saml2解析相同键多值SAML 2声明

无法创建工具窗口(用于VBIDE、VBA的COM加载项扩展)