• .NET 6.0 —— Json(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
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    Pytest单元测试框架实战之Pytest用例运行规则
    Pytest单元测试框架实战之-Pytest环境安装
    Monkey稳定性测试实战之ADB命令(二)
    Jenkins配置报告与邮件插件
    如何对用户体验进行测试?
    Jmeter性能测试实战之java.net.BindException: Address already in use报错解决方案
    测试过程杂记(三)Linux执行yum命令报错
    Jenkins持续集成实战之解决windows搭建jenkins执行selenium无法启动浏览器
    测试框架中工具类的实现
    《Python自动化测试修炼宝典》线上课程已经成功入驻网易云课堂......
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/15784991.html
Copyright © 2020-2023  润新知