ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

.NET 6.0 —— Json(TODO)

2022-01-10 16:33:49  阅读:114  来源: 互联网

标签:Text JSON System Json using NET 序列化 TODO


https://www.zhihu.com/question/449756804

 

作者:醉书生
链接:https://www.zhihu.com/question/449756804/answer/2219422015
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

系统.文本.Json

System.Text.Json提供了多种高性能的 API 来处理 JSON 文档。在过去的几个版本中,我们添加了新功能,以进一步提高 JSON 处理性能并减轻想要从. 此版本包括在这条道路上的继续,并且是性能的重大进步,特别是在序列化器源生成器方面。NewtonSoft.Json

JsonSerializer 源代码生成

注意:应重新编译使用 .NET 6 RC1 或更早版本的源代码生成的应用程序。

几乎所有 .NET 序列化程序的支柱都是反射。反射对于某些场景来说是一项很棒的功能,但不能作为高性能云原生应用程序(通常(反)序列化和处理大量 JSON 文档)的基础。反射是启动、内存使用和程序集修整的问题

运行时反射的替代方案是编译时源代码生成。在 .NET 6 中,我们将一个"https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/">新的源生成器作为System.Text.Json. JSON 源生成器可与JsonSerializer多种方式结合使用并可进行配置。

它可以提供以下好处:

  • 减少启动时间
  • 提高序列化吞吐量
  • 减少私有内存使用
  • 删除运行时使用和System.ReflectionSystem.Reflection.Emit
  • IL 修整兼容性

默认情况下,JSON 源生成器为给定的可序列化类型发出序列化逻辑。JsonSerializer通过生成Utf8JsonWriter直接使用的源代码,这提供了比使用现有方法更高的性能。简而言之,源代码生成器提供了一种在编译时为您提供不同实现的方法,以便使运行时体验更好。

给定一个简单类型:

namespace Test
{
    internal class JsonMessage
    {
        public string Message { get; set; }
    }
}

源生成器可以配置为为示例JsonMessage类型的实例生成序列化逻辑。请注意,类名JsonContext是任意的。您可以为生成的源使用任何您想要的类名。

using System.Text.Json.Serialization;

namespace Test
{
    [JsonSerializable(typeof(JsonMessage)]
    internal partial class JsonContext : JsonSerializerContext
    {
    }
}

使用此模式的序列化程序调用可能类似于以下示例。此示例提供了可能的最佳性能。

using MemoryStream ms = new();
using Utf8JsonWriter writer = new(ms);

JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage);
writer.Flush();

// Writer contains:
// {"Message":"Hello, world!"}

最快和最优化的源代码生成模式——基于Utf8JsonWriter——目前仅可用于序列化。Utf8JsonReader根据您的反馈,未来可能会提供类似的反序列化支持——基于——。

源生成器还发出类型元数据初始化逻辑,这也有利于反序列化。要反序列化JsonMessage使用预生成类型元数据的实例,您可以执行以下操作:

作者:醉书生
链接:https://www.zhihu.com/question/449756804/answer/2219422015
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);

JsonSerializer 支持 IAsyncEnumerable

现在,可以(反)序列化JSON阵列IAsyncEnumerable<T>与。以下示例使用流作为数据的任何异步源的表示。源可以是本地机器上的文件,也可以是数据库查询或 Web 服务 API 调用的结果。System.Text.Json

JsonSerializer.SerializeAsync已更新以识别IAsyncEnumerable值并提供特殊处理。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;

static async IAsyncEnumerable<int> PrintNumbers(int n)
{
    for (int i = 0; i < n; i++) yield return i;
}

using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data); // prints {"Data":[0,1,2]}

IAsyncEnumerable值仅支持使用异步序列化方法。尝试使用同步方法进行序列化将导致NotSupportedException抛出异常。

流式反序列化需要一个新的 API 返回. 我们为此目的添加了该方法,您可以在以下示例中看到。IAsyncEnumerable<T>JsonSerializer.DeserializeAsyncEnumerable

using System;
using System.IO;
using System.Text;
using System.Text.Json;

var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream))
{
    Console.WriteLine(item);
}

此示例将按需反序列化元素,并且在使用特别大的数据流时非常有用。它只支持从根级 JSON 数组中读取,尽管将来可能会根据反馈放宽。

现有DeserializeAsync方法名义上支持,但在其非流式方法签名的范围内。它必须将最终结果作为单个值返回,如下例所示。IAsyncEnumerable<T>

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;

var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
var result = await JsonSerializer.DeserializeAsync<MyPoco>(stream);
await foreach (int item in result.Data)
{
    Console.WriteLine(item);
}

public class MyPoco
{
    public IAsyncEnumerable<int> Data { get; set; }
}

在此示例中,反序列化器将IAsyncEnumerable在返回反序列化对象之前缓冲内存中的所有内容。这是因为反序列化器需要在返回结果之前消耗整个 JSON 值。

作者:醉书生
链接:https://www.zhihu.com/question/449756804/answer/2219422015
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

System.Text.Json:可写 DOM 功能

写JSON DOM功能增加了一个新的简单的,高性能的编程模型的。这个新的 API 很有吸引力,因为它避免了需要强类型的序列化契约,并且与现有类型相比,DOM 是可变的。System.Text.JsonJsonDocument

这个新的 API 有以下好处:

  • 在不可能或不希望使用POCO类型的情况下,或者当 JSON 模式不固定且必须检查时,序列化的轻量级替代方案。
  • 允许对大树的子集进行有效修改。例如,可以高效地导航到大型 JSON 树的子部分并从该子部分读取数组或反序列化 POCO。LINQ 也可以与它一起使用。

以下示例演示了新的编程模型。

    // Parse a JSON object
    JsonNode jNode = JsonNode.Parse("{"MyProperty":42}");
    int value = (int)jNode["MyProperty"];
    Debug.Assert(value == 42);
    // or
    value = jNode["MyProperty"].GetValue<int>();
    Debug.Assert(value == 42);

    // Parse a JSON array
    jNode = JsonNode.Parse("[10,11,12]");
    value = (int)jNode[1];
    Debug.Assert(value == 11);
    // or
    value = jNode[1].GetValue<int>();
    Debug.Assert(value == 11);

    // Create a new JsonObject using object initializers and array params
    var jObject = new JsonObject
    {
        ["MyChildObject"] = new JsonObject
        {
            ["MyProperty"] = "Hello",
            ["MyArray"] = new JsonArray(10, 11, 12)
        }
    };

    // Obtain the JSON from the new JsonObject
    string json = jObject.ToJsonString();
    Console.WriteLine(json); // {"MyChildObject":{"MyProperty":"Hello","MyArray":[10,11,12]}}

    // Indexers for property names and array elements are supported and can be chained
    Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue<int>() == 11);

ReferenceHandler.IgnoreCycles



JsonSerializer(System.Text.Json)现在支持在序列化对象图时忽略循环的能力。该选项的行为与 Newtonsoft.Json 相似。一个主要区别是 System.Text.Json 实现用JSON 标记替换引用循环,而不是忽略对象引用。ReferenceHandler.IgnoreCyclesReferenceLoopHandling.Ignorenull

您可以在以下示例中看到 的行为。在这种情况下,属性被序列化,因为它否则会创建一个循环。ReferenceHandler.IgnoreCyclesNextnull

class Node
{
    public string Description { get; set; }
    public object Next { get; set; }
}

void Test()
{
    var node = new Node { Description = "Node 1" };
    node.Next = node;

    var opts = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles };

    string json = JsonSerializer.Serialize(node, opts);
    Console.WriteLine(json); // Prints {"Description":"Node 1","Next":null}
}

 

 

作者:醉书生
链接:https://www.zhihu.com/question/449756804/answer/2219422015
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:Text,JSON,System,Json,using,NET,序列化,TODO
来源: https://www.cnblogs.com/panpanwelcome/p/15784991.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有