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

Erw*_*ers 3 c# json json.net asp.net-web-api

我有一个模型如下:

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; } }
}
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

当我检查JSON结果时,它确实包含所有TestResultModels,但是TestResultListModel(TotalTestCasesTotalSuccesful)上的属性不可见.

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

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

dbc*_*dbc 8

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

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

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

要强制序列化集合的属性,请使用以下标记对其进行标记[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; } }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果这样做,则不会序列化项目,因为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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这给出了如下的JSON:

{
  "TotalTestCases": 4,
  "TotalSuccessful": 2,
  "Items": [
    {
      "Successful": false,
      "ErrorMessage": "STRING"
    },
    {
      "Successful": true,
      "ErrorMessage": "STRING"
    },
    {
      "Successful": false,
      "ErrorMessage": "STRING"
    },
    {
      "Successful": true,
      "ErrorMessage": "STRING"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

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