在.Net Core 3.0中尝试新的System.Text.Json API

匿名 (未验证) 提交于 2019-12-03 00:15:02

.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序。在此博客文章中,我将介绍它如何工作以及如何使用。
官方文档

  • 如果以.NET Core为目标,请安装.NET Core 3.0及以上版本,该版本提供了新的JSON库和ASP.NET Core集成。
  • 如果以.NET Standard或.NET Framework为目标。安装System.Text.Json NuGet软件包(确保安装.NET Framework4.6.0或更高版本)。为了与ASP.NET Core集成,必须以.NET Core 3.0为目标。

新的JSON API通过使用Span进行性能优化,并且可以直接处理UTF-8,而无需转码为UTF-16 string 实例。这两个方面对于ASP.NET Core都是至关重要的,在ASP.NET Core中,吞吐量是关键要求。使用System.Text.Json,可以将速度提高大约1.3倍至5倍。

using System.Text.Json; using System.Text.Json.Serialization;
  • 学习.Net Core最好的方式是查看源码,下面是JsonSerializer Serialize的部分源码:
namespace System.Text.Json {     public static partial class JsonSerializer     {         /// <summary>         /// Convert the provided value into a <see cref="System.String"/>.         /// </summary>         /// <returns>A <see cref="System.String"/> representation of the value.</returns>         /// <param name="value">The value to convert.</param>         /// <param name="options">Options to control the conversion behavior.</param>         /// <remarks>Using a <see cref="System.String"/> is not as efficient as using UTF-8         /// encoding since the implementation internally uses UTF-8. See also <see cref="SerializeToUtf8Bytes"/>         /// and <see cref="SerializeAsync"/>.         /// </remarks>         public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null)         {             return ToStringInternal(value, typeof(TValue), options);         }          /// <summary>         /// Convert the provided value into a <see cref="System.String"/>.         /// </summary>         /// <returns>A <see cref="System.String"/> representation of the value.</returns>         /// <param name="value">The value to convert.</param>         /// <param name="inputType">The type of the <paramref name="value"/> to convert.</param>         /// <param name="options">Options to control the conversion behavior.</param>         /// <remarks>Using a <see cref="System.String"/> is not as efficient as using UTF-8         /// encoding since the implementation internally uses UTF-8. See also <see cref="SerializeToUtf8Bytes"/>         /// and <see cref="SerializeAsync"/>.         /// </remarks>         public static string Serialize(object value, Type inputType, JsonSerializerOptions options = null)         {             VerifyValueAndType(value, inputType);              return ToStringInternal(value, inputType, options);         }          private static string ToStringInternal(object value, Type inputType, JsonSerializerOptions options)         {             return WriteCoreString(value, inputType, options);         }     } }

可以看到序列化最终调用的是ToStringInternal这个方法。

  • 示例
class Sample {     public DateTimeOffset Date { get; set; }     public string Summary { get; set; } }  string Serialize(Sample value) {     return JsonSerializer.Serialize<Sample>(value); } //obj string SerializeObj(object value) {     return JsonSerializer.Serialize(value); }

JsonSerializerOptions用于在序列化时设置配置, 例如处理注释,null处理,尾随逗号和命名策略。

 public static string ToJson(this object obj)  {     var options = new JsonSerializerOptions() { IgnoreNullValues = true, WriteIndented = true, AllowTrailingCommas = true };     return JsonSerializer.Serialize(obj, options);  }
 Sample Deserialize(string json) {     var options = new JsonSerializerOptions     {         AllowTrailingCommas = true     };      return JsonSerializer.Deserialize<Sample>(json, options); }

可以使用自定义属性来控制序列化行为,例如,忽略属性或者指定属性的名称:

class Sample {     //忽略     [JsonIgnore]     public DateTimeOffset Date { get; set; }     //指定名称     [JsonPropertyName("test")]     public string Summary { get; set; } }

有时,不想反序列化JSON但仍然希望对其内容进行结构化访问,这时可以使用JsonDocument

var options = new JsonDocumentOptions     {         AllowTrailingCommas = true     }; using (JsonDocument document = JsonDocument.Parse(json, options)) {     //todo      foreach (JsonElement element in document.RootElement.EnumerateArray())      {         DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();          //todo      } }
var options = new JsonWriterOptions {     Indented = true };  using (var stream = new MemoryStream()) {     using (var writer = new Utf8JsonWriter(stream, options))     {         writer.WriteStartObject();         writer.WriteString("date", DateTimeOffset.UtcNow);         writer.WriteEndObject();     }      string json = Encoding.UTF8.GetString(stream.ToArray());     Console.WriteLine(json); }
byte[] data = Encoding.UTF8.GetBytes(json); Utf8JsonReader reader = new Utf8JsonReader(data, isFinalBlock: true, state: default);  while (reader.Read()) {     Console.Write(reader.TokenType);      switch (reader.TokenType)     {         case JsonTokenType.PropertyName:         case JsonTokenType.String:         {             string text = reader.GetString();             Console.Write(" ");             Console.Write(text);             break;         }          case JsonTokenType.Number:         {             int value = reader.GetInt32();             Console.Write(" ");             Console.Write(value);             break;         }     }      Console.WriteLine(); }

The System.Text.Json library parses and writes DateTime and DateTimeOffset values according to the ISO 8601:-2019 extended profile. Converters provide custom support for serializing and deserializing with JsonSerializer. Custom support can also be implemented when using Utf8JsonReader and Utf8JsonWriter.

具体请参考官方文档
示例:

 public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>     {         /// <summary>         /// 日期格式         /// </summary>         public string dateTimeFormat { get; }         /// <summary>         /// ctor         /// </summary>               /// <param name="dateTimeFormat"></param>         public DateTimeConverterUsingDateTimeParse(string dateTimeFormat)         {             this.dateTimeFormat = dateTimeFormat;         }         public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)         {             Debug.Assert(typeToConvert == typeof(DateTime));             return DateTime.Parse(reader.GetString());         }          public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)         {             writer.WriteStringValue(value.ToString(dateTimeFormat));         }     }
 public static class JsonHelper     {         /// <summary>Converts to json.</summary>         /// <param name="obj">The object.</param>         /// <param name="dateTimeFormat">The date time format.</param>         /// <returns>System.String.</returns>         public static string ToJson(this object obj, string dateTimeFormat = "yyyy-MM-dd")         {             var options = new JsonSerializerOptions() { IgnoreNullValues = true, WriteIndented = true };             options.Converters.Add(new DateTimeConverterUsingDateTimeParse(dateTimeFormat));             return JsonSerializer.Serialize(obj, options);         }     }
  • 在.NET Core 3.0中,System.Text.Json API提供对JSON的内置支持,包括reader/writer,只读DOM和序列化器/反序列化器。
  • 主要目标是实现高性能和低内存分配。
  • ASP.NET Core 3.0包括对System.Text.Json的支持,默认情况下启用。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!