一尘不染

JSON对类继承列表上的属性进行序列化

json

我有一个模型如下:

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],但没有成功。


阅读 296

收藏
2020-07-27

共1个答案

一尘不染

您的基本困难是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; } }
}

当然,如果执行此操作, 则不会对项目进行序列化
,因为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"
    }
  ]
}

由于这些属性可以在客户端轻松地重建,因此可能比其价值还多。

2020-07-27