JSON序列化类继承名单上的性能 [英] JSON serialize properties on class inheriting list

查看:185
本文介绍了JSON序列化类继承名单上的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型如下:

 公共类TestResultModel
{
    公共BOOL成功{搞定;组; }
    公共字符串的ErrorMessage {搞定;组; }
}公共类TestResultListModel:列表< TestResultModel>
{
    公众诠释TotalTestCases {{返回base.Count; }}    公众诠释TotalSuccessful {{返回base.FindAll(T => t.Successful).Count之间; }}
}

我回到这个 TestResultListModel ApiController

  VAR testResultListModel =新TestResultListModel();
的foreach(新变种INT testCaseId [] {1,2,3,4})
{
    VAR testResultModel =新TestResultModel
    {
        成功= TRUE,
        的ErrorMessage =STRING
    };    testResultListModel.Add(testResultModel);
}
返回testResultListModel;

当我检查JSON导致它包含所有的 TestResultModel S,但对性能的 TestResultListModel TotalTestCases TotalSuccesful )是不可见的。

如何才能还包括在JSON序列化对象,这些价值?

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


解决方案

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


  • 数组是值的有序集合。数组始于 [(左括号)和结束] (右括号)。值由分离(逗号)。


  • 的对象是一个无序的名称/值对。一个对象是以 {(左括号)和结束} (右括号)。


要强制集合的性质是系列化,与 <$ C $标记它C> [JSONObject的]

  [的JSONObject]
公共类TestResultListModel:列表&LT; TestResultModel&GT;
{
    公众诠释TotalTestCases {{返回base.Count; }}    公众诠释TotalSuccessful {{返回base.FindAll(T =&GT; t.Successful).Count之间; }}
}

当然,如果你这样做,的项目将不被序列化后,因为一个JSON容器可以有属性,或项目 - 但不能同时使用。如果你想同时,你将需要添加合成数组属性举行的项目 - 如果你想它可以是私有的。

[JSONObject的] 也会导致基类的属性,如的 容量 被序列化,你可能不想要的。共进晚餐preSS基类的属性,使用 MemberSerialization。选择启用 。因此,你的最后一类应该是这个样子:

  [JSONObject的(MemberSerialization = MemberSerialization.OptIn)
公共类TestResultListModel:列表&LT; TestResultModel&GT;
{
    [JsonProperty]
    公众诠释TotalTestCases {{返回base.Count; }}    [JsonProperty]
    //使用Enumerable.Count()是更多的内存比List.FindAll效率()
    公众诠释TotalSuccessful {{返回this.Count(T =&GT; t.Successful); }}    [JsonProperty]
    TestResultModel []项目
    {
        得到
        {
            返回this.ToArray();
        }
        组
        {
            如果(值!= NULL)
                this.AddRange(值);
        }
    }
}

这给了JSON,看起来像:


  {
  TotalTestCases:4,
  TotalSuccessful:2,
  项目:
    {
      成功:假的,
      的ErrorMessage:STRING
    },
    {
      成功:真实,
      的ErrorMessage:STRING
    },
    {
      成功:假的,
      的ErrorMessage:STRING
    },
    {
      成功:真实,
      的ErrorMessage:STRING
    }
  ]
}


有可能更多的工作比它的价值,因为这些属性可以很容易地在客户端上进行重建。 (这个问题为什么不从列表继承?建议避免这种设计。)

I have a model as follows:

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

I return this TestResultListModel from an 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;

When I inspect the JSON result it does contain all the TestResultModels, but the properties on the TestResultListModel (TotalTestCases and TotalSuccesful) are not visible.

How can I also include these values in the JSON-serialized object?

What I tried is using JSON.NET and decorating the properties with the attribute [JsonProperty], this was unsuccessful.

解决方案

Your basic difficulty here is that JSON has two types of container: an object, and an array. From the standard:

  • An array is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).

  • An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).

To force a collection's properties to be serialized, mark it with [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; } }
}

Of course, if you do this, the items will not be serialized, because a JSON container can have properties, or items -- but not both. If you want both, you will need to add a synthetic array property to hold the items -- which can be private if you want.

[JsonObject] will also cause base class properties such as Capacity to be serialized, which you likely do not want. To suppress base class properties, use MemberSerialization.OptIn. Thus your final class should look something like:

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

This gives JSON that looks like:

{
  "TotalTestCases": 4,
  "TotalSuccessful": 2,
  "Items": [
    {
      "Successful": false,
      "ErrorMessage": "STRING"
    },
    {
      "Successful": true,
      "ErrorMessage": "STRING"
    },
    {
      "Successful": false,
      "ErrorMessage": "STRING"
    },
    {
      "Successful": true,
      "ErrorMessage": "STRING"
    }
  ]
}

It is possibly more work than it's worth, since these properties could be reconstructed easily on the client side. (The question Why not inherit from List? suggests avoiding this sort of design.)

这篇关于JSON序列化类继承名单上的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆