如何在 C# 中使用 Newtonsoft 将两个属性序列化为一个 json 属性?

How to serialize two attributes into one json property using Newtonsoft in C#?

提问人:rutonggaoya 提问时间:10/10/2023 最后编辑:rutonggaoya 更新时间:10/10/2023 访问量:124

问:

在 ScanInfo 类中,有两个版本的扫描结果。但是这两个属性中只有一个是空的,另一个属性是有价值的。在这种情况下,我只想序列化非空属性,输出 json 属性名称为“scanResult”。当我尝试序列化时,当前代码将报告属性名称冲突。我该如何解决这个问题?

public class ScanInfo
{
    [JsonProperty("scanResult", NullValueHandling = NullValueHandling.Ignore)]
    public ScanResult oldVersion;

    [JsonProperty("scanResult", NullValueHandling = NullValueHandling.Ignore)]
    public ScanResultNew newVersion;

}

public class ScanResult 
{
    public DateTime StartTime;
    public DateTime EndTime;
    public IDictionary<string, long> statistic;
}
public class ScanResultNew 
{
    public DateTime StartTime;
    public DateTime EndTime;
    public Statistic statistic;
    public string status;
}

Json输出:

{
    "scanResult":...
}

在此处输入图像描述

我的目标是只序列化其中一个,并且都应该由属性名称“scanResult”引用。

C# JSON json.net

评论

3赞 dbc 10/10/2023
请您编辑您的问题,将您的代码作为文本而不是屏幕截图包含在内吗?关于堆栈溢出图像不应用于帖子中的文本内容,请参阅为什么我不应该上传代码/数据/错误的图像?有关格式设置的说明,请参阅如何设置代码块的格式?
0赞 dbc 10/10/2023
当你说“属性”是“空的”时,你是什么意思?这两个属性实际上具有不同的返回类型吗?你能编辑你的问题以分享一个最小的可重复的例子吗?
0赞 rutonggaoya 10/10/2023
谢谢!我修改了描述。

答:

5赞 Lars Kristensen 10/10/2023 #1

一种解决方案是将该属性添加到两个当前字段,并添加序列化为“scanResult”的新公共属性。这个新属性可以对要序列化的结果进行“筛选”。[JsonIgnore]ScanResult

下面是一个示例:

public class ScanInfo
{
    [JsonIgnore]
    public ScanResult oldVersion;

    [JsonIgnore]
    public ScanResult newVersion;

    [JsonProperty("scanResult", NullValueHandling = NullValueHandling.Ignore)]
    public ScanResult ActualScanResult
    {
        get
        {
            if(newVersion != null) 
            {
                return newVersion;
            }
            else
            {
                return oldVersion;
            }
        }
    }
}

这是一个快速的gif,表明它有效:

Screen recording while debugging the code, to show that the solution works.

评论

0赞 rutonggaoya 10/10/2023
谢谢拉尔斯!不错的解决方案。但我的情况是这两个属性基于两个不同的类(ScanResult 和 ScanResultNew)。两个类定义是不同的。
0赞 rutonggaoya 10/10/2023
使用接受两种不同类型的实例也有效!非常感谢!Object
1赞 Lars Kristensen 10/10/2023
@rutonggaoya啊,对不起,我错过了你问题的那部分。是的,将新属性的类型设置为可以解决它,但我建议给两个类一个接口(例如)并将属性设置为返回该接口的实例。如果我的回答有助于解决您的问题,请将其标记为可接受的解决方案。objectIScanResult
0赞 rutonggaoya 10/10/2023
谢谢!使用接口是合理的。但这两个类的领域却大不相同。他们有一些相同的领域,他们有自己独特的领域。是否可以使用单个接口来接受它?IScanResult
0赞 Sigmarod 10/10/2023
@rutonggaoya 您可以将相同的字段添加到界面中。请记住,如果要访问该类唯一的字段,则必须将 ActualScanResult 强制转换为相应的类。