我的模型如下:
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; } }
}
我从TestResultListModel
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;
当我检查JSON结果时,它确实包含所有TestResultModel
个,但TestResultListModel
(TotalTestCases
和TotalSuccesful
)上的属性不可见。
如何在JSON序列化对象中包含这些值?
我尝试使用JSON.NET
并使用属性[JsonProperty]
修饰属性,这是不成功的。
答案 0 :(得分:7)
这里的基本困难是JSON有两种类型的容器:一个对象和一个数组。来自standard:
数组是有序的值集合。数组以[
(左括号)开头,以]
(右括号)结尾。值以,
(逗号)分隔。
对象是一组无序的名称/值对。对象以{
(左大括号)开头,以}
(右大括号)结束。
要强制序列化集合的属性,请使用[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; } }
}
当然,如果你这样做,这些项目将不会被序列化,因为JSON容器可以包含属性或项目 - 但不能同时包含两者。如果你想要两者,你需要添加一个合成数组属性来保存项目 - 如果你愿意,可以是私有的。
[JsonObject]
还会导致基类属性(如Capacity
)被序列化,这可能是您不想要的。要禁止基类属性,请使用MemberSerialization.OptIn
。因此,您的最终课程应该类似于:
[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);
}
}
}
这使得JSON看起来像:
{ "TotalTestCases": 4, "TotalSuccessful": 2, "Items": [ { "Successful": false, "ErrorMessage": "STRING" }, { "Successful": true, "ErrorMessage": "STRING" }, { "Successful": false, "ErrorMessage": "STRING" }, { "Successful": true, "ErrorMessage": "STRING" } ] }
这可能比它的价值更多,因为这些属性可以在客户端轻松重建。 (问题Why not inherit from List?建议避免这种设计。)