JSON序列化类继承列表的属性

时间:2016-02-16 17:36:29

标签: c# json asp.net-web-api json.net

我的模型如下:

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个,但TestResultListModelTotalTestCasesTotalSuccesful)上的属性不可见。

如何在JSON序列化对象中包含这些值?

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

1 个答案:

答案 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?建议避免这种设计。)