ASP.NET核心将属性强制转换为基类

yb3bgrhw  于 2022-12-14  发布在  .NET
关注(0)|答案(2)|浏览(130)

我有两个“数据”类:

public class BaseData
{
    public string BaseDataStuff { get; set; }
}

public class ChildData : BaseData
{
    public string ChildDataStuff { get; set; }
}

和“容器”类:

public class Container
{
    public BaseData Data { get; set; }
}


然后我有下面的控制器:

public class Controller : ControllerBase
{
    private readonly ChildData Data;
    private readonly Container Container;
    public Controller()
    {
        Data = new ChildData()
        {
            BaseDataStuff = "base stuff",
            ChildDataStuff = "child stuff"
        };

        Container = new Container()
        {
            Data = Data
        };
    }

    [HttpGet("data")]
    public ActionResult<BaseData> GetData() => Ok(Container.Data);

    [HttpGet("container")]
    public ActionResult<Container> GetContainer() => Ok(Container);

}

第一个方法只返回ChildData示例,当我 swagger 地运行它时,我得到了我所期望的JSON:

{
  "childDataStuff": "child stuff",
  "baseDataStuff": "base stuff"
}

当我通过swagger运行第二个方法时,它看起来像是将ChildData示例转换为BaseData

{
  "data": {
    "baseDataStuff": "base stuff"
    }
}

有人能解释一下这里发生了什么吗?

njthzxwz

njthzxwz1#

这个问题很有趣。请参见How to serialize properties of derived classes with System.Text.Json
在那里,它解释了System.Text.Json在.NET 7之前没有按照您想要的方式处理多态对象的序列化。有一些变通方法,但这些方法允许您在根对象是多态(在您的情况下是容器)但不是根的成员(BaseData和ChildData)时进行序列化。
在.NET 7中,您可以这样做

using System.Text.Json.Serialization;

[JsonDerivedType(typeof(ChildData))]
public class BaseData
{
    public string BaseDataStuff { get; set; } = string. Empty;
}

以及

public class ChildData : BaseData
{
    public string ChildDataStuff { get; set; } = string. Empty;
}

以及

public class Container
{
    public BaseData Data { get; set; } = new BaseData();
}

然后这个

var data = new ChildData()
        {
            BaseDataStuff = "base stuff",
            ChildDataStuff = "child stuff"
        };

var container = new Container 
{
    Data = data
};

jsonString = JsonSerializer.Serialize(container);
Console.WriteLine(jsonString);

给你

{"Data":{"ChildDataStuff":"child stuff","BaseDataStuff":"base stuff"}}

我想这正是你想要的。当然,去。NET 7可能不太方便。

bmp9r5qi

bmp9r5qi2#

您可以尝试将自己序列化为like this

options = new JsonSerializerOptions
{
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize<object>(Container, options);

或者另一种选择,就是显式地将它们标记为对于序列化程序是可序列化的:

[DataContract]
  public class BaseData
  {
    [DataMember]
    public string BaseDataStuff { get; set; }
  }

  [DataContract]
  public class ChildData : BaseData
  {
    [DataMember]
    public string ChildDataStuff { get; set; }
  }

相关问题