JSON serialize properties on class inheriting list(JSON序列化类继承列表上的属性)
问题描述
我有一个模型如下:
公共类TestResultModel{公共布尔成功{得到;放;}公共字符串错误消息 { 获取;放;}}公共类 TestResultListModel : 列表<TestResultModel>{公共 int TotalTestCases { get { return base.Count;} }public int TotalSuccessful { get { return base.FindAll(t => t.Successful).Count;} }}
我从 ApiController
返回此 TestResultListModel
:
var testResultListModel = new TestResultListModel();foreach (var testCaseId in new int[] {1,2,3,4}){var testResultModel = 新的 TestResultModel{成功 = 真,错误消息 = "字符串"};testResultListModel.Add(testResultModel);}返回测试结果列表模型;
当我检查 JSON 结果时,它确实包含所有 TestResultModel
,但 TestResultListModel
上的属性(TotalTestCases
和 TotalSuccesful
) 不可见.
如何在 JSON 序列化对象中也包含这些值?
我尝试的是使用 JSON.NET
并使用属性 [JsonProperty]
装饰属性,但没有成功.
这里的基本困难是 JSON 有两种类型的容器:对象和数组.来自标准:
数组是值的有序集合.数组以
[
(左括号)开始,以]
(右括号)结束.值由,
(逗号)分隔.对象是一组无序的名称/值对.一个对象以
{
(左大括号)开始并以}
(右大括号)结束.
要强制对集合的属性进行序列化,请将其标记为 [JsonObject]
:
[JsonObject]公共类 TestResultListModel : 列表<TestResultModel>{公共 int TotalTestCases { get { return base.Count;} }public int TotalSuccessful { get { return base.FindAll(t => t.Successful).Count;} }}
当然,如果您这样做,项目将不会被序列化,因为 JSON 容器可以具有属性或项目 - 但不能同时具有两者.如果你想要两者,你将需要添加一个合成数组属性来保存项目——如果你愿意,它可以是私有的.
[JsonObject]
还会导致基类属性,例如 Capacity
被序列化,你可能不想要.要禁止基类属性,请使用 MemberSerialization.OptIn
一个>.因此,您的最终课程应如下所示:
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]公共类 TestResultListModel : 列表<TestResultModel>{[Json 属性]公共 int TotalTestCases { get { return base.Count;} }[Json 属性]//使用 Enumerable.Count() 比 List.FindAll() 更节省内存public int TotalSuccessful { get { return this.Count(t => t.Successful);} }[Json 属性]TestResultModel[] 项{得到{返回 this.ToArray();}放{如果(值!= null)this.AddRange(值);}}}
这给出的 JSON 看起来像:
<块引用><代码>{总测试案例":4,总成功":2,项目": [{成功":错误,错误消息":字符串"},{成功":真的,错误消息":字符串"},{成功":错误,错误消息":字符串"},{成功":真的,错误消息":字符串"}]}
这可能比它的价值更多,因为这些属性可以在客户端轻松重建.(为什么不从 List 继承?这个问题建议避免这种设计.)
I have a model as follows:
public class TestResultModel
{
public bool Successful { get; set; }
public string ErrorMessage { get; set; }
}
public class TestResultListModel : List<TestResultModel>
{
public int TotalTestCases { get { return base.Count; } }
public int TotalSuccessful { get { return base.FindAll(t => t.Successful).Count; } }
}
I return this TestResultListModel
from an ApiController
:
var testResultListModel = new TestResultListModel();
foreach (var testCaseId in new int[] {1,2,3,4})
{
var testResultModel = new TestResultModel
{
Successful = true,
ErrorMessage = "STRING"
};
testResultListModel.Add(testResultModel);
}
return testResultListModel;
When I inspect the JSON result it does contain all the TestResultModel
s, but the properties on the TestResultListModel
(TotalTestCases
and TotalSuccesful
) are not visible.
How can I also include these values in the JSON-serialized object?
What I tried is using JSON.NET
and decorating the properties with the attribute [JsonProperty]
, this was unsuccessful.
Your basic difficulty here is that JSON has two types of container: an object, and an array. From the standard:
An array is an ordered collection of values. An array begins with
[
(left bracket) and ends with]
(right bracket). Values are separated by,
(comma).An object is an unordered set of name/value pairs. An object begins with
{
(left brace) and ends with}
(right brace).
To force a collection's properties to be serialized, mark it with [JsonObject]
:
[JsonObject]
public class TestResultListModel : List<TestResultModel>
{
public int TotalTestCases { get { return base.Count; } }
public int TotalSuccessful { get { return base.FindAll(t => t.Successful).Count; } }
}
Of course, if you do this, the items will not be serialized, because a JSON container can have properties, or items -- but not both. If you want both, you will need to add a synthetic array property to hold the items -- which can be private if you want.
[JsonObject]
will also cause base class properties such as Capacity
to be serialized, which you likely do not want. To suppress base class properties, use MemberSerialization.OptIn
. Thus your final class should look something like:
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class TestResultListModel : List<TestResultModel>
{
[JsonProperty]
public int TotalTestCases { get { return base.Count; } }
[JsonProperty]
// Using Enumerable.Count() is more memory efficient than List.FindAll()
public int TotalSuccessful { get { return this.Count(t => t.Successful); } }
[JsonProperty]
TestResultModel[] Items
{
get
{
return this.ToArray();
}
set
{
if (value != null)
this.AddRange(value);
}
}
}
This gives JSON that looks like:
{ "TotalTestCases": 4, "TotalSuccessful": 2, "Items": [ { "Successful": false, "ErrorMessage": "STRING" }, { "Successful": true, "ErrorMessage": "STRING" }, { "Successful": false, "ErrorMessage": "STRING" }, { "Successful": true, "ErrorMessage": "STRING" } ] }
It is possibly more work than it's worth, since these properties could be reconstructed easily on the client side. (The question Why not inherit from List? suggests avoiding this sort of design.)
这篇关于JSON序列化类继承列表上的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:JSON序列化类继承列表上的属性
- 为什么 C# 中的堆栈大小正好是 1 MB? 2022-01-01
- 在 LINQ to SQL 中使用 contains() 2022-01-01
- Azure Active Directory 与 MVC,客户端和资源标识同一 2022-01-01
- Windows 喜欢在 LINUX 中使用 MONO 进行服务开发? 2022-01-01
- CanBeNull和ReSharper-将其用于异步任务? 2022-01-01
- 是否可以在 .Net 3.5 中进行通用控件? 2022-01-01
- 使用 rss + c# 2022-01-01
- 在 C# 中异步处理项目队列 2022-01-01
- C# 通过连接字符串检索正确的 DbConnection 对象 2022-01-01
- 带问号的 nvarchar 列结果 2022-01-01