【问题标题】:JSON serialize properties on class inheriting list [duplicate]JSON序列化类继承列表上的属性[重复]
【发布时间】:2016-02-16 17:36:29
【问题描述】:

我有一个模型如下:

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; } }
}

我从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 结果时,它确实包含所有 TestResultModels,但 TestResultListModelTotalTestCasesTotalSuccesful)上的属性不可见。

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

我尝试使用JSON.NET 并使用属性[JsonProperty] 装饰属性,但没有成功。

【问题讨论】:

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


    【解决方案1】:

    这里的基本困难在于 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? 建议避免这种设计。)

    【讨论】:

    • 感谢您的详尽回答。我会重新考虑设计。 :)
    猜你喜欢
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多