JSON序列化类inheritance列表的属性

我有一个模型如下:

public class TestResultModel { public bool Successful { get; set; } public string ErrorMessage { get; set; } } public class TestResultListModel : List { public 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 = new TestResultModel { Successful = true, ErrorMessage = "STRING" }; testResultListModel.Add(testResultModel); } return testResultListModel; 

当我检查JSON结果时,它确实包含所有TestResultModel ,但TestResultListModelTotalTestCasesTotalSuccesful )上的属性不可见。

我怎样才能在JSON序列化对象中包含这些值?

我尝试使用JSON.NET并使用属性[JsonProperty]装饰属性,这是不成功的。

这里你的基本困难是JSON有两种类型的容器:一个对象和一个数组。 从标准 :

  • 数组是有序的值集合。 数组以[ (左括号)开头并以]结尾(右括号)。 值以(逗号)分隔。

  • 对象是一组无序的名称/值对。 对象以{ (左括号)开头,以}结尾(右括号)。

要强制序列化集合的属性,请使用[JsonObject]标记它:

 [JsonObject] public class TestResultListModel : List { 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 { [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" } ] } 

它可能比它的价值更多,因为这些属性可以在客户端轻松重建。 (问题为什么不从Listinheritance?建议避免这种设计。)