• JSON部分序列化(二)


    当序列化.Net对象为Json对象时经常会遇到的一个问题是:最终的Json包含大量多余的属性和属性值。这个问题在返回Json到客户端时显得特别重要。Json越大意味着需要更大的带宽,使网速变得更慢。

    为了解决多余的Json这个问题,Json.Net有一系列内置的选项可以进行调整。

    ->JsonIgnoreAttribute and DataMemberAttribute

    默认情况下,在Json创建的时候Json.Net会包含所有类级别的public属性和字段。添加JsonIgnoreAttribute到属性上,告诉序列化器序列化时跳过它。

     public class Car
        {
            // included in JSON
            public string Model { get; set; }
            public DateTime Year { get; set; }
            public List<string> Features { get; set; }

            // ignored
            [JsonIgnore]
            public DateTime LastModified { get; set; }
        }

    如果类有很多属性,你只想序列化它的一小部分,添加JsonIgore到所有其他的属性上会比较冗余,也比较容易出错。有一种用来处理这种情况的方法,添加DataContractAttribute到类上,添加DataMemberAttribute到需要被序列化的属性上。与使用JsonIgnoreAttribute的opt-out序列化相比,opt-in序列化仅仅你标记的属性被需列化。

    using System.Runtime.Serialization;

      [DataContract]
        public class Computer
        {
            // included in JSON
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public decimal SalePrice { get; set; }

            // ignored
            public string Manufacture { get; set; }
            public int StockCount { get; set; }
            public decimal WholeSalePrice { get; set; }
            public DateTime NextShipmentDate { get; set; }
        }

    ->Formatting

    Json序列化时,用可选参数Formatting.Indented生成良好的显示格式,可读性更好。另一方面,Formatting.None会跳过不必要的空格和换行符,让Json的结果更小。生成的显示格式更加紧凑,也许效率更高。

    ->NullValueHandling

       在序列化器中NullVlaueHandling是可选的。它控制序列化器如何处理值为null的属性。通过设置NullValueHandling.Ignore值,序列化器会跳过值为null的属性。

      public class Movie
        {
            public string Name { get; set; }
            public string Description { get; set; }
            public string Classification { get; set; }
            public string Studio { get; set; }
            public DateTime? ReleaseDate { get; set; }
            public List<string> ReleaseCountries { get; set; }
        }

    测试1:

               Movie movie = new Movie();
                movie.Name = "Bad Boys III";
                movie.Description = "It's no Bad Boys";

                string included = JsonConvert.SerializeObject(movie,
                  Formatting.Indented,
                  new JsonSerializerSettings { });
                Console.WriteLine(included);

    输出结果:

    {
      "Name": "Bad Boys III",
      "Description": "It's no Bad Boys",
      "Classification": null,
      "Studio": null,
      "ReleaseDate": null,
      "ReleaseCountries": null
    }

    测试2:

               string ignored = JsonConvert.SerializeObject(movie,
                  Formatting.Indented,
                  new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
                Console.WriteLine(ignored);

    输出结果:

    {
      "Name": "Bad Boys III",
      "Description": "It's no Bad Boys"
    }

    NullValueHandling也可以在单独的属性上用JsonPropertyAttribute进行定制。使用JsonPropertyAttribute时设置的NullValueHandling值会在Json序列化器中为该属性进行重写。

    ->DefaultValuehandling

       在序列化器中DefaultValuehandling是可选的。它控制序列化器如何处理带有默认值的属性。通过设置DefaultValuehandling.Ignore值,序列化器会跳过带有默认值的属性。对于引用类型为null,对于值类型,如int和DateTime,序列化器将跳过默认未初使化值的值类型。

      Json.Net也允许你通过DefaultValueAttribute自定义默认值,例如:如果一个字符串类型的属性Department在它的默认状态下总是返回一个空字符,但是在你的Json对象中你不想要那个空字符串,你可以在Department上使用空字符串参数标记DefaultValueAttribute,这意味着Department在序列化时不再写入Json中,除非它有非空值。

      public class Invoice
        {
            public string Company { get; set; }
            public decimal Amount { get; set; }

            // false is default value of bool
            public bool Paid { get; set; }
            // null is default value of nullable
            public DateTime? PaidDate { get; set; }

            // customize default values
            [DefaultValue(30)]
            public int FollowUpDays { get; set; }
            [DefaultValue("")]
            public string FollowUpEmailAddress { get; set; }
        }

    测试1:

               Invoice invoice = new Invoice
                {
                    Company = "Acme Ltd.",
                    Amount = 50.0m,
                    Paid = false,
                    FollowUpDays = 30,
                    FollowUpEmailAddress = string.Empty,
                    PaidDate = null
                };

                string includedDefaultValue = JsonConvert.SerializeObject(invoice,
                  Formatting.Indented,
                  new JsonSerializerSettings { });
                Console.WriteLine(includedDefaultValue);

    输出结果:

    {
      "Company": "Acme Ltd.",
      "Amount": 50.0,
      "Paid": false,
      "PaidDate": null,
      "FollowUpDays": 30,
      "FollowUpEmailAddress": ""
    }

    测试2:

                string ignoredDefaultValue = JsonConvert.SerializeObject(invoice,
                  Formatting.Indented,
                  new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
                Console.WriteLine(ignoredDefaultValue);

    输出结果:

    {
      "Company": "Acme Ltd.",
      "Amount": 50.0,
      "Paid": false//??
    }

    DefaultValueHandling也可以在单独的属性上用JsonPropertyAttribute进行定制。使用JsonPropertyAttribute时设置的DefaultValueHandling值会在Json序列化器中为该属性进行重写。

    ->IContractResolver

      为了获得更多的灵活性,IContractResolver接口提供了定制.Net对象序列化为Json的每一个方面,包括在运行时改变序列化的行为。

     public class DynamicContractResolver : DefaultContractResolver
        {
            private readonly char _startingWithChar;
            public DynamicContractResolver(char startingWithChar)
            {
                _startingWithChar = startingWithChar;
            }

            protected override IList<JsonProperty> CreateProperties(JsonObjectContract contract)
            {
                IList<JsonProperty> properties = base.CreateProperties(contract);

                // only serializer properties that start with the specified character
                properties =
                  properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();

                return properties;
            }
        }

        public class Book
        {
            public string BookName { get; set; }
            public decimal BookPrice { get; set; }
            public string AuthorName { get; set; }
            public int AuthorAge { get; set; }
            public string AuthorCountry { get; set; }
        }

    测试:

               Book book = new Book
                {
                    BookName = "The Gathering Storm",
                    BookPrice = 16.19m,
                    AuthorName = "Brandon Sanderson",
                    AuthorAge = 34,
                    AuthorCountry = "United States of America"
                };

                string startingWithA = JsonConvert.SerializeObject(book, Formatting.Indented,
                  new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('A') });
                Console.WriteLine(startingWithA);
                // {
                //   "AuthorName": "Brandon Sanderson",
                //   "AuthorAge": 34,
                //   "AuthorCountry": "United States of America"
                // }

                string startingWithB = JsonConvert.SerializeObject(book, Formatting.Indented,
                  new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('B') });
                Console.WriteLine(startingWithA);
                // {
                //   "BookName": "The Gathering Storm",
                //   "BookPrice": 16.19
                // }

  • 相关阅读:
    libevent
    /dev/poll, kqueue(2), event ports, POSIX select(2), Windows select(), poll(2), and epoll(4)
    Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化
    How to Design a Good API and Why it Matters
    cloud native
    Service Mesh服务网格:是什么和为什么
    唯品会的Service Mesh三年进化史 2018 年 Service Mesh 元年,被誉为是下一代微服务架构
    干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?
    Gradle
    Why did we build Zuul? How We Use Zuul At Netflix
  • 原文地址:https://www.cnblogs.com/MyFlora/p/2451261.html
Copyright © 2020-2023  润新知