NewtonSoft.JSON官方手册中文版【连载12】

缩小序列化的JSON的大小

在把.NET对象序列化为JSON时可能的一个常见的问题是,JSON最终包含了很多不想要的属性和值。在把JSON返回到客户端时,它可能会特别显著。更大的JSON意味着占用更大的带宽和产生更慢的网站。

为了解决不想要的JSON的问题,Json.NET有很多的内置选项,来细调序列化对象中会写入哪些内容。

JsonIgnoreAttribute和DataMemberAttribute

默认情况下,Json.NET将在它创建的JSON中包含一个类的所有公开的属性和字段。把JsonIgnoreAttribute添加到属性上,会告诉序列化器始终跳过把此属性写入JSON结果。

Opt-out序列化示例

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

如果一个类具有很多属性,你可能只想序列化它的一个小小的子集,则对所有的其它属性添加JsonIgnore会很麻烦,容易出错。解决这种情况的办法是给类添加DataContractAttribute,给要序列化的属性添加DataMemberAttribute。这是opt-in序列化——只有你标记了的属性才会被序列化,而不像opt-out序列化那样使用JsonIgnoreAttrubute。

Opt-in序列化示例

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

格式化

序列化器编写的JSON,如果其选项Formatting设置为Indented,会产生格式化良好的、容易阅读的JSON,在开发时非常有利于可读性。另一方面,Formatting.None会使JSON结果尽可能小,跳过所有不必要的空格和分行,以产生更紧凑的高效的JSON。

空值处理

NullValueHandling是JsonSerializer上的一个选项,控制了序列化器如何处理带有空值的属性。如果设置了值NullValueHandling.Ignore,则JsonSerializer将跳过写入任何带有空值的属性。

NullValueHandling类

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

NullValueHandling忽略示例

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 { });
// {
//   "Name": "Bad Boys III",
//   "Description": "It's no Bad Boys",
//   "Classification": null,
//   "Studio": null,
//   "ReleaseDate": null,
//   "ReleaseCountries": null
// }
string ignored = JsonConvert.SerializeObject(movie,
  Formatting.Indented,
  new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
// {
//   "Name": "Bad Boys III",
//   "Description": "It's no Bad Boys"
// }

还可以使用JsonPropertyAttribute,在单个属性上自定义NullValueHandling。JsonPropertyAttribute的值NullValueHandling将针对此属性覆盖JsonSerializer上的设置。

默认值处理

DefaultValueHandling是JsonSerializer上的一个选项,控制了序列化器处理带有默认值的属性的方式。设置值DefaultValueHandling.Ignore将使JsonSerializer跳过把任何带有默认值的属性写入到JSON结果中。对于对象引用,默认值是null。对于值类型,像int和DateTime,序列化器将针对这些值类型,跳过默认的未初始化的值。

Json.NET还允许你利用DefaultValueAttribute来自定义单个属性的默认值是什么。例如,如果一个称为Department的字符串属性在它的默认状态中始终返回一个空字符串,而且你不想要在JSON中有空字符串,则在Department上放置DefaultValueAttribute,带上那个值,意味着Department将不再会写入到JSON中,除非它具有值。

DefaultValueHandling示例

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

DefaultValueHandling忽略示例

Invoice invoice = new Invoice
{
  Company = "Acme Ltd.",
  Amount = 50.0m,
  Paid = false,
  FollowUpDays = 30,
  FollowUpEmailAddress = string.Empty,
  PaidDate = null
};
string included = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { });
// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0,
//   "Paid": false,
//   "PaidDate": null,
//   "FollowUpDays": 30,
//   "FollowUpEmailAddress": ""
// }
string ignored = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0
// }

可以在单个属性上利用JsonPropertyAttribute自定义DefaultValueHandling。JsonPropertyAttribute的值DefaultValueHandling将针对此属性覆盖JsonSerializer上的设置。

IContractResolver

为了更大的灵活性,IContractResolver提供了一个接口,来自定义关于.NET对象如何序列化为JSON的几乎所有的方面,包括在运行时改变序列化行为。

IContractResolver示例

public class DynamicContractResolver : DefaultContractResolver
{
  private readonly char _startingWithChar;
  public DynamicContractResolver(char startingWithChar)
  {
      _startingWithChar = startingWithChar;
  }
  protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  {
      IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
      // 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; }
}

IContractResolver示例

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') });
// {
//   "AuthorName": "Brandon Sanderson",
//   "AuthorAge": 34,
//   "AuthorCountry": "United States of America"
// }
string startingWithB = JsonConvert.SerializeObject(book, Formatting.Indented,
  new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('B') });
// {
//   "BookName": "The Gathering Storm",
//   "BookPrice": 16.19
// }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值