如何解决为什么WebApi在json响应中返回内部类的属性 情况我的尝试
我的 Api 返回一个实际上是内部的属性,我不希望返回这样的属性。
情况
我有一个带有公共属性的简单公共类 Bar
,以及一个继承自 FooBar
并为公共属性做广告的内部类 Bar
。但是,由于类是内部的,因此该属性实际上也是内部的,而不是公共的。
public class Bar
{
public string PublicPropertyInPublicBaseClass { get; set; }
}
internal class FooBar : Bar
{
public string PublicPropertyInInternalClass { get; set; }
}
我的控制器操作指定它返回一个 Bar
,但它返回的实际实例是 FooBar
类型。
[HttpGet]
public Bar Get()
{
return new FooBar();
}
控制器动作返回:
{"publicPropertyInInternalClass":null,"publicPropertyInPublicBaseClass":null}
我希望 Json 序列化程序仅公开指定类型 (Bar
) 的属性,因此我不期望 publicPropertyInInternalClass
。即使它期望公开实际类型的属性,我也希望它永远不会公开内部类型的属性。
我的尝试
如果我理解正确,.NET Core 3.1 及更高版本使用 System.Text.Json 而不是旧的 NewtonSoft.Json。我写了一个简单的测试来看看 System.Text.Json 会做什么以及 NewtonSoft.Json 会做什么。
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestNetCoreSerializer()
{
Bar sut = CreateBar();
var serialized = System.Text.Json.JsonSerializer.Serialize(sut);
Debug.WriteLine(serialized);
// {"PublicPropertyInPublicBaseClass":null}
}
[TestMethod]
public void TestNewtonSoftSerializer()
{
Bar sut = CreateBar();
var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(sut);
Debug.WriteLine(serialized);
// {"PublicPropertyInInternalClass":null,"PublicPropertyInPublicBaseClass":null}
}
private static Bar CreateBar()
{
// We actually return a FooBar,which inherits from Bar
return new FooBar();
}
}
所以现在我很困惑。 System.Text.Json 序列化程序只公开真正公开的属性,我希望控制器使用该序列化程序。但是控制器返回的似乎是 NewtonSoft.Json 行为。
这里发生了什么?我看到的行为是否符合预期?为什么?为什么序列化程序会序列化实际类型?为什么 NewtonSoft.Json 和 System.Text.Json 之间有这种不同?
也许是最重要的问题:如果内部类继承自公共类,而该公共类是我的 API 输出模型的一部分,我是否做错了什么?或者通过在 public
类中拥有 internal
属性?
我也在 .NET Core 3.1 和 .NET 5.0 中尝试过这个。
解决方法
这里发生了什么?我看到的行为是否符合预期?为什么?为什么序列化程序会序列化实际类型?为什么 NewtonSoft.Json 和 System.Text.Json 之间有这种不同?
首先我需要说,通过在我的项目中使用您的代码,它得到了相同的结果 ({"PublicPropertyInInternalClass":null,"PublicPropertyInPublicBaseClass":null}
)。
你可能会误解 the usage of internal access modifier。如果属性被 internal
标记,则意味着它只能在同一程序集中的文件中访问。
一种情况:
如果您使用两个程序集,则需要将内部访问修饰符添加到属性 而不是类 em>,然后您可以在另一个程序集中创建实例但无法访问内部成员:
组装 1:
public class Bar
{
public string PublicPropertyInPublicBaseClass { get; set; }
}
public class FooBar : Bar
{
internal string PublicPropertyInInternalClass { get; set; }
}
Assembly2:
[HttpGet]
public string Get()
{
var data = new Assembly1.Models.FooBar();
var serialized = System.Text.Json.JsonSerializer.Serialize(data);
var serialized2 = Newtonsoft.Json.JsonConvert.SerializeObject(data);
return serialized;
}
注意:如果您在 asp.net core 3.x 或 asp.net 5 中使用 Newtonsoft.Json
,请记得在下面添加 Newtonsoft 支持,更多详情请参阅answer here。否则,您仍然会得到这个结果({"PublicPropertyInInternalClass":null,"PublicPropertyInPublicBaseClass":null}
)。
services.AddControllersWithViews()
.AddNewtonsoftJson();
另一种情况:
如果您在同一程序集中使用模型,则可以使用 [JsonIgnore]
属性:
public class Bar
{
public string PublicPropertyInPublicBaseClass { get; set; }
}
internal class FooBar : Bar
{
[JsonIgnore]
public string PublicPropertyInInternalClass { get; set; }
}
注意:NewtonSoft.Json
和 System.Text.Json
都包含 JsonIgnore
属性。确保添加正确的包引用:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。