{"id":834,"date":"2024-11-03T17:57:27","date_gmt":"2024-11-04T01:57:27","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/?p=834"},"modified":"2024-11-03T17:57:27","modified_gmt":"2024-11-04T01:57:27","slug":"net-9-%e4%b8%adsystem-text-json-%e7%9a%84%e6%96%b0%e5%a2%9e%e5%8a%9f%e8%83%bd","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/net-9-%e4%b8%adsystem-text-json-%e7%9a%84%e6%96%b0%e5%a2%9e%e5%8a%9f%e8%83%bd\/","title":{"rendered":".NET 9 \u4e2dSystem.Text.Json \u7684\u65b0\u589e\u529f\u80fd\u00a0"},"content":{"rendered":"<p style=\"text-align: left;\"><em>\u672c\u7bc7\u7ffb\u8bd1\u4e8eEirik Tsarpalis\u7684\u00a0<a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/system-text-json-in-dotnet-9\/\">What&#8217;s new in System.Text.Json in .NET 9 &#8211; .NET Blog<\/a>\u00a0<\/em><\/p>\n<p><span data-contrast=\"auto\">System.Text.Json<\/span><span data-contrast=\"auto\">\u7684<\/span><span data-contrast=\"auto\">9.0 <\/span><span data-contrast=\"auto\">\u7248\u672c\u5305\u542b\u8bb8\u591a\u529f\u80fd\uff0c\u4e3b\u8981\u4fa7\u91cd\u4e8e<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u67b6\u6784\u548c\u667a\u80fd\u5e94\u7528\u7a0b\u5e8f\u652f\u6301\u3002\u5b83\u8fd8\u5305\u62ec\u4e00\u4e9b\u5907\u53d7\u671f\u5f85\u7684\u589e\u5f3a\u529f\u80fd\uff0c\u4f8b\u5982\u53ef\u7a7a\u5f15\u7528\u7c7b\u578b\u652f\u6301\u3001\u81ea\u5b9a\u4e49\u679a\u4e3e\u6210\u5458\u540d\u79f0\u3001\u65e0\u5e8f\u5143\u6570\u636e\u53cd\u5e8f\u5217\u5316\u548c\u81ea\u5b9a\u4e49\u5e8f\u5217\u5316\u7f29\u8fdb<\/span><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h3><b><span data-contrast=\"auto\">\u83b7\u53d6\u6700\u65b0\u4fe1\u606f<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h3>\n<p><span data-contrast=\"auto\">\u60a8\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528<\/span> <a href=\"https:\/\/www.nuget.org\/packages\/System.Text.Json\"><span data-contrast=\"auto\">System.Text.Json NuGet <\/span><span data-contrast=\"none\">\u5305<\/span><\/a><span data-contrast=\"auto\">\u7684\u6700\u65b0\u7248\u672c\u6216<\/span> <a href=\"https:\/\/dotnet.microsoft.com\/en-us\/download\/dotnet\/9.0\"><span data-contrast=\"auto\">.NET 9 <\/span><span data-contrast=\"auto\">\u7684\u6700\u65b0<\/span><span data-contrast=\"none\"> SDK<\/span><\/a> <span data-contrast=\"auto\">\u6765\u5c1d\u8bd5\u65b0\u529f\u80fd<\/span><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2><b><span data-contrast=\"auto\">JSON <\/span><\/b><b><span data-contrast=\"auto\">\u67b6\u6784\u5bfc\u51fa\u5668<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u65b0\u7684<\/span><span data-contrast=\"auto\"> JsonSchemaExporter <\/span><span data-contrast=\"auto\">\u7c7b\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\"> JsonSerializerOptions <\/span><span data-contrast=\"auto\">\u6216<\/span><span data-contrast=\"auto\"> JsonTypeInfo <\/span><span data-contrast=\"auto\">\u5b9e\u4f8b\u4ece<\/span><span data-contrast=\"auto\"> .NET <\/span><span data-contrast=\"auto\">\u7c7b\u578b\u4e2d\u63d0\u53d6<\/span> <a href=\"https:\/\/json-schema.org\/\"><span data-contrast=\"auto\">JSON <\/span><span data-contrast=\"none\">\u67b6\u6784<\/span><\/a><span data-contrast=\"auto\">\u6587\u6863<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">using System.Text.Json.Schema;\r\n\r\nJsonSerializerOptions options = JsonSerializerOptions.Default;\r\nJsonNode schema = options.GetJsonSchemaAsNode(typeof(Person));\r\nConsole.WriteLine(schema.ToString());\r\n\/\/{\r\n\/\/  \"type\": [\"object\", \"null\"],\r\n\/\/  \"properties\": {\r\n\/\/    \"Name\": { \"type\": \"string\" },\r\n\/\/    \"Age\": { \"type\": \"integer\" },\r\n\/\/    \"Address\": { \"type\": [\"string\", \"null\"], \"default\": null }\r\n\/\/  },\r\n\/\/  \"required\": [\"Name\", \"Age\"]\r\n\/\/}\r\n\r\nrecord Person(string Name, int Age, string? Address = null);<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u751f\u6210\u7684\u6a21\u5f0f\u4e3a\u8be5\u7c7b\u578b\u63d0\u4f9b\u4e86<\/span><span data-contrast=\"auto\">JSON<\/span><span data-contrast=\"auto\">\u5e8f\u5217\u5316\u5951\u7ea6\u7684\u89c4\u8303\u3002\u4ece\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\u53ef\u4ee5\u770b\u51fa\uff0c\u5b83\u533a\u5206\u4e86\u53ef\u7a7a\u5c5e\u6027\u548c\u4e0d\u53ef\u7a7a\u5c5e\u6027\uff0c\u5e76\u6839\u636e\u6784\u9020\u51fd\u6570\u53c2\u6570\u662f\u5426\u53ef\u9009\u6765\u586b\u5145<\/span><span data-contrast=\"auto\">\u201crequired\u201d<\/span><span data-contrast=\"auto\">\u5173\u952e\u5b57\u3002\u6a21\u5f0f\u7684\u8f93\u51fa\u53ef\u4ee5\u901a\u8fc7\u5728<\/span><span data-contrast=\"auto\"> JsonSerializerOptions <\/span><span data-contrast=\"auto\">\u6216<\/span><span data-contrast=\"auto\"> JsonTypeInfo <\/span><span data-contrast=\"auto\">\u5b9e\u4f8b\u4e2d\u6307\u5b9a\u7684\u914d\u7f6e\u8fdb\u884c\u5f71\u54cd<\/span><span data-contrast=\"auto\">:<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new(JsonSerializerOptions.Default)\r\n{\r\n    PropertyNamingPolicy = JsonNamingPolicy.KebabCaseUpper,\r\n    NumberHandling = JsonNumberHandling.WriteAsString,\r\n    UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,\r\n};\r\n\r\nJsonNode schema = options.GetJsonSchemaAsNode(typeof(MyPoco));\r\nConsole.WriteLine(schema.ToString());\r\n\/\/{\r\n\/\/  \"type\": [\"object\", \"null\"],\r\n\/\/  \"properties\": {\r\n\/\/    \"NUMERIC-VALUE\": {\r\n\/\/      \"type\": [\"string\", \"integer\"],\r\n\/\/      \"pattern\": \"^-?(?:0|[1-9]\\\\d*)$\"\r\n\/\/    }\r\n\/\/  },\r\n\/\/  \"additionalProperties\": false\r\n\/\/}\r\n\r\nclass MyPoco\r\n{\r\n    public int NumericValue { get; init; }\r\n}<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u7528\u6237\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\"> JsonSchemaExporterOptions <\/span><span data-contrast=\"auto\">\u914d\u7f6e\u7c7b\u578b\u8fdb\u4e00\u6b65\u63a7\u5236\u751f\u6210\u7684\u6a21\u5f0f\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = JsonSerializerOptions.Default;\r\nJsonSchemaExporterOptions exporterOptions = new()\r\n{\r\n    \/\/ Marks root-level types as non-nullable\r\n    TreatNullObliviousAsNonNullable = true,\r\n};\r\n\r\nJsonNode schema = options.GetJsonSchemaAsNode(typeof(Person), exporterOptions);\r\nConsole.WriteLine(schema.ToString());\r\n\/\/{\r\n\/\/  \"type\": \"object\",\r\n\/\/  \"properties\": {\r\n\/\/    \"Name\": { \"type\": \"string\" }\r\n\/\/  },\r\n\/\/  \"required\": [\"Name\"]\r\n\/\/}\r\n\r\nrecord Person(string Name);<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u6700\u540e\uff0c\u7528\u6237\u53ef\u4ee5\u901a\u8fc7\u6307\u5b9a<\/span><span data-contrast=\"auto\"> TransformSchemaNode <\/span><span data-contrast=\"auto\">\u59d4\u6258<\/span><span data-contrast=\"auto\">,<\/span> <span data-contrast=\"auto\">\u5bf9\u751f\u6210\u7684\u67b6\u6784\u8282\u70b9\u5e94\u7528\u81ea\u5df1\u7684\u8f6c\u6362\u3002\u4ee5\u4e0b\u662f\u5305\u542b\u6765\u81ea<\/span><span data-contrast=\"auto\"> DescriptionAttribute <\/span><span data-contrast=\"auto\">\u6ce8\u91ca\u7684\u6587\u672c\u7684\u793a\u4f8b<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSchemaExporterOptions exporterOptions = new()\r\n{\r\n    TransformSchemaNode = (context, schema) =&gt;\r\n    {\r\n        \/\/ Determine if a type or property and extract the relevant attribute provider\r\n        ICustomAttributeProvider? attributeProvider = context.PropertyInfo is not null\r\n            ? context.PropertyInfo.AttributeProvider\r\n            : context.TypeInfo.Type;\r\n\r\n        \/\/ Look up any description attributes\r\n        DescriptionAttribute? descriptionAttr = attributeProvider?\r\n            .GetCustomAttributes(inherit: true)\r\n            .Select(attr =&gt; attr as DescriptionAttribute)\r\n            .FirstOrDefault(attr =&gt; attr is not null);\r\n\r\n        \/\/ Apply description attribute to the generated schema\r\n        if (descriptionAttr != null)\r\n        {\r\n            if (schema is not JsonObject jObj)\r\n            {\r\n                \/\/ Handle the case where the schema is a boolean\r\n                JsonValueKind valueKind = schema.GetValueKind();\r\n                Debug.Assert(valueKind is JsonValueKind.True or JsonValueKind.False);\r\n                schema = jObj = new JsonObject();\r\n                if (valueKind is JsonValueKind.False)\r\n                {\r\n                    jObj.Add(\"not\", true);\r\n                }\r\n            }\r\n\r\n            jObj.Insert(0, \"description\", descriptionAttr.Description);\r\n        }\r\n\r\n        return schema;\r\n    }\r\n};<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u7efc\u5408\u4ee5\u4e0a\u5185\u5bb9\uff0c\u6211\u4eec\u73b0\u5728\u53ef\u4ee5\u751f\u6210\u4e00\u4e2a\u5305\u542b\u6765\u81ea\u5c5e\u6027\u6ce8\u91ca\u7684<\/span><span data-contrast=\"auto\">description<\/span><span data-contrast=\"auto\">\u5173\u952e\u5b57\u6e90\u7684\u6a21\u5f0f<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonNode schema = options.GetJsonSchemaAsNode(typeof(Person), exporterOptions);\r\nConsole.WriteLine(schema.ToString());\r\n\/\/{\r\n\/\/  \"description\": \"A person\",\r\n\/\/  \"type\": [\"object\", \"null\"],\r\n\/\/  \"properties\": {\r\n\/\/    \"Name\": { \"description\": \"The name of the person\", \"type\": \"string\" }\r\n\/\/  },\r\n\/\/  \"required\": [\"Name\"]\r\n\/\/}\r\n\r\n[Description(\"A person\")]\r\nrecord Person([property: Description(\"The name of the person\")] string Name);<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u5728\u4e3a<\/span><span data-contrast=\"auto\"> .NET <\/span><span data-contrast=\"auto\">\u65b9\u6cd5\u6216<\/span><span data-contrast=\"auto\"> API <\/span><span data-contrast=\"auto\">\u751f\u6210\u67b6\u6784\u65f6\uff0c\u8fd9\u662f\u4e00\u4e2a\u7279\u522b\u6709\u7528\u7684\u7ec4\u4ef6\uff1b\u5b83\u88ab\u7528\u4e8e\u652f\u6301<\/span><span data-contrast=\"auto\"> ASP.NET Core <\/span><span data-contrast=\"auto\">\u6700\u65b0\u53d1\u5e03\u7684<\/span><span data-contrast=\"auto\"> OpenAPI <\/span><span data-contrast=\"auto\">\u7ec4\u4ef6\uff0c\u5e76\u4e14\u6211\u4eec\u5df2\u5c06\u5176\u90e8\u7f72\u5230\u8bb8\u591a\u5177\u6709\u5de5\u5177\u8c03\u7528\u8981\u6c42\u7684<\/span><span data-contrast=\"auto\"> AI <\/span><span data-contrast=\"auto\">\u76f8\u5173\u5e93\u548c\u5e94\u7528\u7a0b\u5e8f\u4e2d\uff0c\u4f8b\u5982<\/span><span data-contrast=\"auto\"> Semantic Kernel\u3001Visual Studio Copilot <\/span><span data-contrast=\"auto\">\u548c\u6700\u65b0\u53d1\u5e03\u7684<\/span><span data-contrast=\"auto\"> Microsoft.Extensions.AI <\/span><span data-contrast=\"auto\">\u5e93<\/span><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2><b><span data-contrast=\"auto\">\u6d41\u5f0f\u5904\u7406\u591a\u4e2a<\/span><\/b><b><span data-contrast=\"auto\"> JSON <\/span><\/b><b><span data-contrast=\"auto\">\u6587\u6863<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">Utf8JsonReader <\/span><span data-contrast=\"auto\">\u73b0\u5728\u652f\u6301\u4ece\u5355\u4e2a\u7f13\u51b2\u533a\u6216\u6d41\u4e2d\u8bfb\u53d6\u591a\u4e2a\u4ee5\u7a7a\u683c\u5206\u9694\u7684<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u6587\u6863\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5982\u679c<\/span><span data-contrast=\"auto\"> Utf8JsonReader <\/span><span data-contrast=\"auto\">\u68c0\u6d4b\u5230\u7b2c\u4e00\u4e2a\u9876\u7ea7\u6587\u6863\u540e\u9762\u6709\u4efb\u4f55\u975e\u7a7a\u683c\u5b57\u7b26\uff0c\u5b83\u5c06\u629b\u51fa<\/span> <span data-contrast=\"auto\">\u5f02\u5e38\u3002\u8fd9\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\"> JsonReaderOptions.AllowMultipleValues <\/span><span data-contrast=\"auto\">\u6807\u5fd7\u6765\u6539\u53d8<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonReaderOptions options = new() { AllowMultipleValues = true };\r\nUtf8JsonReader reader = new(\"null {} 1 \\r\\n [1,2,3]\"u8, options);\r\n\r\nreader.Read();\r\nConsole.WriteLine(reader.TokenType); \/\/ Null\r\n\r\nreader.Read();\r\nConsole.WriteLine(reader.TokenType); \/\/ StartObject\r\nreader.Skip();\r\n\r\nreader.Read();\r\nConsole.WriteLine(reader.TokenType); \/\/ Number\r\n\r\nreader.Read();\r\nConsole.WriteLine(reader.TokenType); \/\/ StartArray\r\nreader.Skip();\r\n\r\nConsole.WriteLine(reader.Read()); \/\/ False<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u6b64\u5916\uff0c\u8fd9\u8fd8\u4f7f\u5f97\u4ece\u53ef\u80fd\u5305\u542b\u65e0\u6548<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u5c3e\u90e8\u6570\u636e\u7684\u6709\u6548\u8d1f\u8f7d\u4e2d\u8bfb\u53d6<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u6210\u4e3a\u53ef\u80fd<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;134245417&quot;:true,&quot;335551550&quot;:1,&quot;335551620&quot;:1}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">Utf8JsonReader reader = new(\"[1,2,3]    &lt;NotJson\/&gt;\"u8, new() { AllowMultipleValues = true });\r\n\r\nreader.Read();\r\nreader.Skip(); \/\/ Success\r\nreader.Read(); \/\/ throws JsonReaderException<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u5728\u6d41\u5f0f\u53cd\u5e8f\u5217\u5316\u65b9\u9762\uff0c\u6211\u4eec\u6dfb\u52a0\u4e86\u65b0\u7684<\/span><span data-contrast=\"auto\"> JsonSerializer.DeserializeAsyncEnumerable <\/span><span data-contrast=\"auto\">\u91cd\u8f7d\uff0c\u4f7f\u6d41\u5f0f\u5904\u7406\u591a\u4e2a\u9876\u7ea7\u503c\u6210\u4e3a\u53ef\u80fd\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c<\/span><span data-contrast=\"auto\">DeserializeAsyncEnumerable <\/span><span data-contrast=\"auto\">\u5c06\u5c1d\u8bd5\u6d41\u5f0f\u5904\u7406\u9876\u7ea7<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u6570\u7ec4\u4e2d\u5305\u542b\u7684\u5143\u7d20\u3002\u8fd9\u53ef\u4ee5\u4f7f\u7528\u65b0\u7684<\/span><span data-contrast=\"auto\"> topLevelValues <\/span><span data-contrast=\"auto\">\u6807\u5fd7\u5207\u6362<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">ReadOnlySpan&lt;byte&gt; utf8Json = \"\"\"[0] [0,1] [0,1,1] [0,1,1,2] [0,1,1,2,3]\"\"\"u8;\r\nusing var stream = new MemoryStream(utf8Json.ToArray());\r\n\r\nawait foreach (int[] item in JsonSerializer.DeserializeAsyncEnumerable&lt;int[]&gt;(stream, topLevelValues: true))\r\n{\r\n    Console.WriteLine(item.Length);\r\n}<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">\u9075\u5faa\u53ef<\/span><\/b><b><span data-contrast=\"auto\">null<\/span><\/b><b><span data-contrast=\"auto\">\u6ce8\u91ca<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">JsonSerializer <\/span><span data-contrast=\"auto\">\u73b0\u5728\u4e3a\u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316\u4e2d\u7684\u975e\u7a7a\u5f15\u7528\u7c7b\u578b\u5f3a\u5236\u589e\u52a0\u4e86\u6709\u9650\u7684\u652f\u6301\u3002\u8fd9\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\"> RespectNullableAnnotations <\/span><span data-contrast=\"auto\">\u6807\u5fd7\u8fdb\u884c\u5207\u6362<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><code class=\"language-default\"><\/code><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">#nullable enable\r\nJsonSerializerOptions options = new() { RespectNullableAnnotations = true };\r\n\r\nMyPoco invalidValue = new(Name: null!);\r\nJsonSerializer.Serialize(invalidValue, options);\r\n\/\/ System.Text.Json.JsonException: The property or field 'Name'\r\n\/\/ on type 'MyPoco' doesn't allow getting null values. Consider\r\n\/\/ updating its nullability annotation. \r\n\r\nrecord MyPoco(string Name);<\/code><code class=\"language-default\">\r\n<\/code><\/pre>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new() { RespectNullableAnnotations = true };\r\nstring json = \"\"\"{\"Name\":null}\"\"\";\r\nJsonSerializer.Deserialize&lt;MyPoco&gt;(json, options);\r\n\/\/ System.Text.Json.JsonException: The constructor parameter 'Name'\r\n\/\/ on type 'MyPoco' doesn't allow null values. Consider updating\r\n\/\/ its nullability annotation.<\/code><\/pre>\n<h3><b><span data-contrast=\"auto\">\u9650\u5236<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h3>\n<p><span data-contrast=\"auto\">\u7531\u4e8e\u975e\u7a7a\u5f15\u7528\u7c7b\u578b\u7684\u5b9e\u73b0\u65b9\u5f0f\uff0c\u6b64\u529f\u80fd\u5e26\u6709\u4e00\u4e9b\u91cd\u8981\u7684\u9650\u5236\uff0c\u7528\u6237\u5728\u542f\u7528\u4e4b\u524d\u9700\u8981\u719f\u6089\u8fd9\u4e9b\u9650\u5236\u3002\u95ee\u9898\u7684\u6839\u6e90\u5728\u4e8e\u5f15\u7528\u7c7b\u578b\u53ef\u7a7a\u6027\u5728<\/span><span data-contrast=\"auto\"> IL <\/span><span data-contrast=\"auto\">\u4e2d\u6ca1\u6709\u4e00\u6d41\u7684\u8868\u793a\u5f62\u5f0f<\/span><span data-contrast=\"auto\">\uff0c<\/span><span data-contrast=\"auto\">\u4f8b\u5982\u4ece\u8fd0\u884c\u65f6\u53cd\u5c04\u7684\u89d2\u5ea6\u6765\u770b\uff0c\u8868\u8fbe\u5f0f<\/span><span data-contrast=\"auto\"> MyPoco <\/span><span data-contrast=\"auto\">\u548c<\/span><span data-contrast=\"auto\"> MyPoco? <\/span><span data-contrast=\"auto\">\u662f<\/span><a href=\"https:\/\/sharplab.io\/#v2:D4AQTAjAsAULAqBPADgUwAQBcLoLzvlQGdMAeAWUQAUB7AYxoD4AKASgG4EUNMw8DiZSrQYB+Fh1iwQEAJzNsefL0kwZANgLcBJUvAl5GWbjQBmzeKul9h9GuyA=\"><span data-contrast=\"none\">\u65e0\u6cd5\u533a\u5206\u7684<\/span><\/a><span data-contrast=\"auto\">\u3002\u867d\u7136\u7f16\u8bd1\u5668\u4f1a\u5c3d<\/span><a href=\"https:\/\/sharplab.io\/#v2:D4AQTAjAsAULBOBTAxge3gEwAQFkCeACqmgBQgQAMWAcqgC7UCuANswMp3wCWAdgOYAaLOQoB+Gi2YBDAEbNEHbvwCUAbiA=\"><span data-contrast=\"auto\">\u53ef\u80fd\u901a\u8fc7<\/span><span data-contrast=\"none\">\u53d1\u51fa\u5c5e\u6027\u5143\u6570\u636e<\/span><\/a><span data-contrast=\"auto\">\u6765\u5f25\u8865\u8fd9\u4e00\u70b9\uff0c\u4f46\u8fd9\u4ec5\u9650\u4e8e\u7279\u5b9a\u7c7b\u578b\u5b9a\u4e49\u8303\u56f4\u5185\u7684\u975e\u6cdb\u578b\u6210\u5458\u6ce8\u89e3\u3002\u6b63\u662f\u51fa\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u8be5\u6807\u5fd7\u4ec5\u9a8c\u8bc1\u975e\u6cdb\u578b\u5c5e\u6027\u3001\u5b57\u6bb5\u548c\u6784\u9020\u51fd\u6570\u53c2\u6570\u4e0a\u5b58\u5728\u7684\u53ef\u7a7a\u6027\u6ce8\u91ca\u3002<\/span><span data-contrast=\"auto\">System.Text.Json <\/span><span data-contrast=\"auto\">\u4e0d\u652f\u6301\u5bf9<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:860,&quot;335559991&quot;:440,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"1\" data-aria-level=\"1\"><span data-contrast=\"auto\">\u9876\u7ea7\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u8fdb\u884c\u7b2c\u4e00\u6b21<\/span><span data-contrast=\"auto\"> JsonSerializer.(De)serialize <\/span><span data-contrast=\"auto\">\u8c03\u7528\u65f6\u4f20\u9012\u7684\u7c7b\u578b\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:860,&quot;335559991&quot;:440,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"2\" data-aria-level=\"1\"><span data-contrast=\"auto\">\u96c6\u5408\u5143\u7d20\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u6211\u4eec\u65e0\u6cd5\u533a\u5206<\/span><span data-contrast=\"auto\"> List&lt;string&gt; <\/span><span data-contrast=\"auto\">\u548c<\/span><span data-contrast=\"auto\"> List&lt;string?&gt; <\/span><span data-contrast=\"auto\">\u7c7b\u578b\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:860,&quot;335559991&quot;:440,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"3\" data-aria-level=\"1\"><span data-contrast=\"auto\">\u4efb\u4f55\u901a\u7528\u7684\u5c5e\u6027\u3001\u5b57\u6bb5\u6216\u6784\u9020\u51fd\u6570\u53c2\u6570<\/span><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/li>\n<\/ul>\n<p><span data-contrast=\"auto\">\u5982\u679c\u60a8\u5e0c\u671b\u5728\u8fd9\u4e9b\u60c5\u51b5\u4e0b\u5f3a\u5236\u6267\u884c\u53ef\u7a7a\u6027\u9a8c\u8bc1\uff0c\u5efa\u8bae\u60a8\u5c06\u7c7b\u578b\u5efa\u6a21\u4e3a<\/span><span data-contrast=\"auto\"> struct<\/span><span data-contrast=\"auto\">\uff08\u56e0\u4e3a\u7ed3\u6784\u4f53\u4e0d\u5141\u8bb8\u7a7a\u503c\uff09\uff0c\u6216\u8005\u7f16\u5199\u4e00\u4e2a\u81ea\u5b9a\u4e49\u8f6c\u6362\u5668\uff0c\u5c06\u5176<\/span> <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.text.json.serialization.jsonconverter-1.handlenull?view=net-8.0\"><span data-contrast=\"auto\">HandleNull <\/span><span data-contrast=\"none\">\u5c5e\u6027<\/span><\/a><span data-contrast=\"auto\">\u91cd\u5199\u4e3a<\/span><span data-contrast=\"auto\"> true\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h3><b><span data-contrast=\"auto\">\u529f\u80fd\u5f00\u5173<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h3>\n<p><span data-contrast=\"auto\">\u7528\u6237\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\"> System.Text.Json.Serialization.RespectNullableAnnotationsDefault <\/span><span data-contrast=\"auto\">\u529f\u80fd\u5f00\u5173\u5168\u5c40\u6253\u5f00<\/span><span data-contrast=\"auto\"> RespectNullableAnnotations <\/span><span data-contrast=\"auto\">\u8bbe\u7f6e\uff0c\u8be5\u5f00\u5173\u53ef\u901a\u8fc7\u9879\u76ee\u914d\u7f6e\u8fdb\u884c\u8bbe\u7f6e<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">&lt;ItemGroup&gt;\r\n  &lt;RuntimeHostConfigurationOption Include=\"System.Text.Json.Serialization.RespectNullableAnnotationsDefault\" Value=\"true\" \/&gt;\r\n&lt;\/ItemGroup&gt;<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">\u53ef\u7a7a\u53c2\u6570\u548c\u53ef\u9009\u53c2\u6570\u4e4b\u95f4\u7684\u5173\u7cfb<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c<\/span><span data-contrast=\"auto\">RespectNullableAnnotations <\/span><span data-contrast=\"auto\">\u4e0d\u4f1a\u5c06\u5f3a\u5236\u6267\u884c\u8303\u56f4\u6269\u5c55\u5230\u672a\u6307\u5b9a\u7684<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u503c<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new() { RespectNullableAnnotations = true };\r\nvar result = JsonSerializer.Deserialize&lt;MyPoco&gt;(\"{}\", options); \/\/ No exception!\r\nConsole.WriteLine(result.Name is null); \/\/ True\r\n\r\nclass MyPoco\r\n{\r\n    public string Name { get; set; }\r\n}<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u8fd9\u662f\u56e0\u4e3a<\/span><span data-contrast=\"auto\"> STJ <\/span><span data-contrast=\"auto\">\u5c06\u5fc5\u9700\u5c5e\u6027\u548c\u975e\u53ef\u7a7a\u5c5e\u6027\u89c6\u4e3a\u6b63\u4ea4\u6982\u5ff5\u3002\u8fd9\u6e90\u4e8e<\/span><span data-contrast=\"auto\"> C# <\/span><span data-contrast=\"auto\">\u8bed\u8a00\u672c\u8eab\uff0c\u5728<\/span><span data-contrast=\"auto\"> C# <\/span><span data-contrast=\"auto\">\u8bed\u8a00\u4e2d\uff0c\u60a8\u53ef\u4ee5\u62e5\u6709\u53ef\u7a7a\u7684<\/span><span data-contrast=\"auto\">required<\/span><span data-contrast=\"auto\">\u5c5e\u6027<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">MyPoco poco = new() { Value = null }; \/\/ No compiler warnings\r\n\r\nclass MyPoco\r\n{\r\n    public required string? Value { get; set; }\r\n}<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u4ee5\u53ca\u4e0d\u53ef\u4e3a\u7a7a\u7684\u53ef\u9009\u5c5e\u6027<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">class MyPoco\r\n{\r\n    public string Value { get; set; } = \"default\";\r\n}<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u540c\u6837\u7684\u6b63\u4ea4\u6027\u4e5f\u9002\u7528\u4e8e\u6784\u9020\u51fd\u6570\u53c2\u6570<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">record MyPoco(\r\n    string RequiredNonNullable,\r\n    string? RequiredNullable,\r\n    string OptionalNonNullable = \"default\",\r\n    string? OptionalNullable = \"default\");<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">\u9075\u5faa\u975e\u53ef\u9009\u7684\u6784\u9020\u51fd\u6570\u53c2\u6570<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u57fa\u4e8e<\/span><span data-contrast=\"auto\"> STJ <\/span><span data-contrast=\"auto\">\u6784\u9020\u51fd\u6570\u7684\u53cd\u5e8f\u5217\u5316\u5386\u6765\u5c06\u6240\u6709\u6784\u9020\u51fd\u6570\u53c2\u6570\u89c6\u4e3a\u53ef\u9009\uff0c\u5982\u4ee5\u4e0b\u793a\u4f8b\u4e2d\u6240\u793a<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">var result = JsonSerializer.Deserialize&lt;Person&gt;(\"{}\");\r\nConsole.WriteLine(result); \/\/ Person { Name = , Age = 0 }\r\n\r\nrecord Person(string Name, int Age);<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u5728<\/span><span data-contrast=\"auto\"> .NET 9 <\/span><span data-contrast=\"auto\">\u4e2d\uff0c\u6211\u4eec\u5305\u542b\u4e86<\/span><span data-contrast=\"auto\"> RespectRequiredConstructorParameters <\/span><span data-contrast=\"auto\">\u6807\u5fd7\uff0c\u8be5\u6807\u5fd7\u4f1a\u6539\u53d8\u884c\u4e3a\uff0c\u4f7f\u5f97\u975e\u53ef\u9009\u7684\u6784\u9020\u51fd\u6570\u53c2\u6570\u73b0\u5728\u88ab\u89c6\u4e3a\u5fc5\u9700\u7684<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new() { RespectRequiredConstructorParameters = true };\r\nstring json = \"\"\"{\"Optional\": \"value\"}\"\"\";\r\nJsonSerializer.Deserialize&lt;MyPoco&gt;(json, options);\r\n\r\nrecord MyPoco(string Required, string? Optional = null);\r\n\/\/ JsonException: JSON deserialization for type 'MyPoco' \r\n\/\/ was missing required properties including: 'Required'.<\/code><\/pre>\n<h3><b><span data-contrast=\"auto\">\u529f\u80fd\u5f00\u5173<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h3>\n<p><span data-contrast=\"auto\">\u7528\u6237\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\">\u00a0<\/span><span data-contrast=\"auto\">System.Text.Json.Serialization.RespectRequiredConstructorParametersDefault <\/span><span data-contrast=\"auto\">\u529f\u80fd\u5f00\u5173\u5168\u5c40\u6253\u5f00<\/span><span data-contrast=\"auto\"> RespectRequiredConstructorParameters <\/span><span data-contrast=\"auto\">\u8bbe\u7f6e\uff0c\u8be5\u5f00\u5173\u53ef\u901a\u8fc7\u9879\u76ee\u914d\u7f6e\u8fdb\u884c\u8bbe\u7f6e<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">&lt;ItemGroup&gt;\r\n  &lt;RuntimeHostConfigurationOption Include=\"System.Text.Json.Serialization.RespectRequiredConstructorParametersDefault\" Value=\"true\" \/&gt;\r\n&lt;\/ItemGroup&gt;<\/code><\/pre>\n<p><span data-contrast=\"auto\">RespectNullableAnnotations <\/span><span data-contrast=\"auto\">\u548c<\/span><span data-contrast=\"auto\"> RespectRequiredConstructorParameter <\/span><span data-contrast=\"auto\">\u5c5e\u6027\u5747\u4f5c\u4e3a\u53ef\u9009\u6807\u8bb0\u5b9e\u73b0\uff0c\u4ee5\u907f\u514d\u7834\u574f\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f\u3002\u5982\u679c\u60a8\u6b63\u5728\u7f16\u5199\u65b0\u5e94\u7528\u7a0b\u5e8f\uff0c\u5f3a\u70c8\u5efa\u8bae\u60a8\u5728\u4ee3\u7801\u4e2d\u542f\u7528\u8fd9\u4e24\u4e2a\u6807\u8bb0<\/span><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2><b><span data-contrast=\"auto\">\u81ea\u5b9a\u4e49\u679a\u4e3e\u6210\u5458\u540d\u79f0<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u65b0\u7684<\/span><span data-contrast=\"auto\"> JsonStringEnumMemberName <\/span><span data-contrast=\"auto\">\u7279\u6027\u53ef\u4ee5\u7528\u6765\u4e3a\u4f5c\u4e3a\u5b57\u7b26\u4e32\u5e8f\u5217\u5316\u7684\u7c7b\u578b\u4e2d\u7684\u5355\u4e2a\u679a\u4e3e\u6210\u5458\u81ea\u5b9a\u4e49\u540d\u79f0\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializer.Serialize(MyEnum.Value1 | MyEnum.Value2); \/\/ \"Value1, Custom enum value\"\r\n\r\n[Flags, JsonConverter(typeof(JsonStringEnumConverter))]\r\nenum MyEnum\r\n{\r\n    Value1 = 1,\r\n    [JsonStringEnumMemberName(\"Custom enum value\")]\r\n    Value2 = 2,\r\n}<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">\u65e0\u5e8f\u5143\u6570\u636e\u8bfb\u53d6<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">System.Text.Json <\/span><span data-contrast=\"auto\">\u7684\u67d0\u4e9b\u529f\u80fd\uff08\u4f8b\u5982\u591a\u6001\u6027\u6216<\/span><span data-contrast=\"auto\"> ReferenceHandler.Preserve\uff09<\/span><span data-contrast=\"auto\">\u9700\u8981\u5728\u6570\u636e\u4f20\u8f93\u4e2d\u53d1\u51fa\u5143\u6570\u636e\u5c5e\u6027\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new() { ReferenceHandler = ReferenceHandler.Preserve };\r\nBase value = new Derived(\"Name\");\r\nJsonSerializer.Serialize(value, options); \/\/ {\"$id\":\"1\",\"$type\":\"derived\",\"Name\":\"Name\"}\r\n\r\n[JsonDerivedType(typeof(Derived), \"derived\")]\r\nrecord Base;\r\nrecord Derived(string Name) : Base;<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c<\/span><span data-contrast=\"auto\">STJ<\/span><span data-contrast=\"auto\">\u5143\u6570\u636e\u8bfb\u53d6\u5668\u8981\u6c42\u5143\u6570\u636e\u5c5e\u6027<\/span><span data-contrast=\"auto\">$id<\/span><span data-contrast=\"auto\">\u548c<\/span><span data-contrast=\"auto\">$type<\/span><span data-contrast=\"auto\">\u5fc5\u987b\u5728<\/span><span data-contrast=\"auto\">JSON<\/span><span data-contrast=\"auto\">\u5bf9\u8c61\u7684\u5f00\u59cb\u5904\u5b9a\u4e49<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializer.Deserialize&lt;Base&gt;(\"\"\"{\"Name\":\"Name\",\"$type\":\"derived\"}\"\"\");\r\n\/\/ JsonException: The metadata property is either not supported by the\r\n\/\/ type or is not the first property in the deserialized JSON object.<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u4f17\u6240\u5468\u77e5\uff0c\u5f53\u9700\u8981\u53cd\u5e8f\u5217\u5316\u4e0d\u662f\u6765\u81ea<\/span><span data-contrast=\"auto\"> System.Text.Json <\/span><span data-contrast=\"auto\">\u7684<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u6709\u6548\u8d1f\u8f7d\u65f6\uff0c\u8fd9\u4f1a\u4ea7\u751f\u95ee\u9898\u3002\u53ef\u4ee5\u914d\u7f6e\u65b0\u7684<\/span><span data-contrast=\"auto\"> AllowOutOfOrderMetadataProperties <\/span><span data-contrast=\"auto\">\u6765\u7981\u7528\u6b64\u9650\u5236<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new() { AllowOutOfOrderMetadataProperties = true };\r\nJsonSerializer.Deserialize&lt;Base&gt;(\"\"\"{\"Name\":\"Name\",\"$type\":\"derived\"}\"\"\", options); \/\/ Success<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u542f\u7528\u6b64\u6807\u5fd7\u65f6\u5e94\u5c0f\u5fc3\u8c28\u614e\uff0c\u56e0\u4e3a\u5728\u5bf9\u975e\u5e38\u5927\u7684<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u5bf9\u8c61\u6267\u884c\u6d41\u5f0f\u53cd\u5e8f\u5217\u5316\u65f6\uff0c\u5b83\u53ef\u80fd\u4f1a\u5bfc\u81f4\u7f13\u51b2\u8fc7\u5ea6\uff08\u548c<\/span><span data-contrast=\"auto\"> OOM <\/span><span data-contrast=\"auto\">\u6545\u969c\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u5143\u6570\u636e\u5c5e\u6027\u5fc5\u987b\u5728\u5b9e\u4f8b\u5316\u53cd\u5e8f\u5217\u5316\u5bf9\u8c61\u4e4b\u524d\u8bfb\u53d6\uff0c\u8fd9\u610f\u5473\u7740\u6240\u6709\u4f4d\u4e8e<\/span><span data-contrast=\"auto\"> $type <\/span><span data-contrast=\"auto\">\u5c5e\u6027\u4e4b\u524d\u7684\u5c5e\u6027\u5fc5\u987b\u4fdd\u7559\u5728\u7f13\u51b2\u533a\u4e2d\uff0c\u4ee5\u4fbf\u540e\u7eed\u7684\u5c5e\u6027\u7ed1\u5b9a\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2><b><span data-contrast=\"auto\">\u81ea\u5b9a\u4e49\u7f29\u8fdb<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">JsonWriterOptions <\/span><span data-contrast=\"auto\">\u548c<\/span><span data-contrast=\"auto\"> JsonSerializerOptions <\/span><span data-contrast=\"auto\">\u7c7b\u578b\u73b0\u5728\u516c\u5f00\u4e86\u7528\u4e8e\u914d\u7f6e\u7f29\u8fdb\u7684<\/span><span data-contrast=\"auto\"> API<\/span><span data-contrast=\"auto\">\u3002\u4ee5\u4e0b\u793a\u4f8b\u542f\u7528\u4e86\u5355\u5236\u8868\u7b26\u7f29\u8fdb<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new()\r\n{\r\n    WriteIndented = true,\r\n    IndentCharacter = '\\t',\r\n    IndentSize = 1,\r\n};\r\n\r\nJsonSerializer.Serialize(new { Value = 42 }, options);<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">JsonObject <\/span><\/b><b><span data-contrast=\"auto\">\u5c5e\u6027\u987a\u5e8f\u64cd\u4f5c<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">JsonObject <\/span><span data-contrast=\"auto\">\u7c7b\u578b\u662f\u53ef\u53d8<\/span><span data-contrast=\"auto\"> DOM <\/span><span data-contrast=\"auto\">\u7684\u4e00\u90e8\u5206\uff0c\u7528\u4e8e\u8868\u793a<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u5bf9\u8c61\u3002\u5c3d\u7ba1\u8be5\u7c7b\u578b\u88ab\u5efa\u6a21\u4e3a<\/span><span data-contrast=\"auto\"> IDictionary&lt;string, JsonNode&gt;<\/span><span data-contrast=\"auto\">\uff0c\u4f46\u5b83\u786e\u5b9e\u5c01\u88c5\u4e86\u7528\u6237\u4e0d\u53ef\u4fee\u6539\u7684\u9690\u5f0f\u5c5e\u6027\u987a\u5e8f\u3002\u65b0\u7248\u672c\u516c\u5f00\u4e86\u5176\u4ed6<\/span><span data-contrast=\"auto\"> API<\/span><span data-contrast=\"auto\">\uff0c\u53ef\u6709\u6548\u5730\u5c06\u8be5\u7c7b\u578b\u5efa\u6a21\u4e3a\u6709\u5e8f\u5b57\u5178<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = new()\r\n{\r\n    WriteIndented = true,\r\n    IndentCharacter = '\\t',\r\n    IndentSize = 1,\r\n};\r\n\r\nJsonSerializer.Serialize(new { Value = 42 }, options);<\/code><\/pre>\n<p><span data-contrast=\"auto\">\u8fd9\u5141\u8bb8\u4fee\u6539\u53ef\u4ee5\u76f4\u63a5\u5f71\u54cd\u5c5e\u6027\u987a\u5e8f\u7684\u5bf9\u8c61\u5b9e\u4f8b\uff1a<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\/\/ Adds or moves the $id property to the start of the object\r\nvar schema = (JsonObject)JsonSerializerOptions.Default.GetJsonSchemaAsNode(typeof(MyPoco));\r\nswitch (schema.IndexOf(\"$id\", out JsonNode? idValue))\r\n{\r\n    case &lt; 0: \/\/ $id property missing\r\n       idValue = (JsonNode)\"https:\/\/example.com\/schema\";\r\n       schema.Insert(0, \"$id\", idValue);\r\n       break;\r\n\r\n    case 0: \/\/ $id property already at the start of the object\r\n        break; \r\n\r\n    case int index: \/\/ $id exists but not at the start of the object\r\n        schema.RemoveAt(index);\r\n        schema.Insert(0, \"$id\", idValue);\r\n}<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">JsonElement <\/span><\/b><b><span data-contrast=\"auto\">\u548c<\/span><\/b><b><span data-contrast=\"auto\"> JsonNode <\/span><\/b><b><span data-contrast=\"auto\">\u4e2d\u7684<\/span><\/b><b><span data-contrast=\"auto\"> DeepEquals <\/span><\/b><b><span data-contrast=\"auto\">\u65b9\u6cd5<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u65b0\u7684<\/span><span data-contrast=\"auto\"> JsonElement.DeepEquals <\/span><span data-contrast=\"auto\">\u65b9\u6cd5\u6269\u5c55\u4e86\u5bf9<\/span><span data-contrast=\"auto\"> JsonElement <\/span><span data-contrast=\"auto\">\u5b9e\u4f8b\u7684\u6df1\u5ea6\u76f8\u7b49\u6bd4\u8f83\uff0c\u8865\u5145\u4e86\u5df2\u6709\u7684<\/span><span data-contrast=\"auto\"> JsonNode.DeepEquals <\/span><span data-contrast=\"auto\">\u65b9\u6cd5\u3002\u6b64\u5916\uff0c\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u5728\u5176\u5b9e\u73b0\u4e2d\u8fdb\u884c\u4e86\u6539\u8fdb\uff0c\u4f8b\u5982\u5904\u7406\u7b49\u6548<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u6570\u5b57\u8868\u793a\u7684\u65b9\u5f0f\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonElement left = JsonDocument.Parse(\"10e-3\").RootElement;\r\nJsonElement right = JsonDocument.Parse(\"0.001\").RootElement;\r\nJsonElement.DeepEquals(left, right); \/\/ True<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">JsonSerializerOptions.Web<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u65b0\u7684<\/span><span data-contrast=\"auto\"> JsonSerializerOptions.Web <\/span><span data-contrast=\"auto\">\u5355\u4f8b\u53ef\u4ee5\u4f7f\u7528<\/span><span data-contrast=\"auto\"> JsonSerializerDefaults.Web <\/span><span data-contrast=\"auto\">\u8bbe\u7f6e\u5feb\u901f\u5e8f\u5217\u5316\u503c<\/span><span data-contrast=\"auto\">\uff1a<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">JsonSerializerOptions options = JsonSerializerOptions.Web; \/\/ used instead of new(JsonSerializerDefaults.Web);\r\nJsonSerializer.Serialize(new { Value = 42 }, options); \/\/ {\"value\":42}<\/code><\/pre>\n<h2><b><span data-contrast=\"auto\">\u6027\u80fd\u6539\u8fdb<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">\u6709\u5173<\/span><span data-contrast=\"auto\"> .NET 9 <\/span><span data-contrast=\"auto\">\u4e2d<\/span><span data-contrast=\"auto\"> System.Text.Json <\/span><span data-contrast=\"auto\">\u6027\u80fd\u6539\u8fdb\u7684\u8be6\u7ec6\u8bf4\u660e\uff0c\u8bf7\u53c2\u9605<\/span><span data-contrast=\"auto\"> Stephen Toub <\/span><span data-contrast=\"auto\">\u7684<\/span><span data-contrast=\"auto\">\u201c.NET 9 <\/span><span data-contrast=\"auto\">\u4e2d\u7684\u6027\u80fd\u6539\u8fdb<\/span><span data-contrast=\"auto\">\u201d<\/span><span data-contrast=\"auto\">\u6587\u7ae0\u4e2d\u7684<\/span><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/performance-improvements-in-net-9\/#json\"><span data-contrast=\"none\">\u76f8\u5173\u90e8\u5206<\/span><\/a><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2><b><span data-contrast=\"auto\">\u7ed3\u675f\u8bed<\/span><\/b><span data-ccp-props=\"{}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">.NET 9 <\/span><span data-contrast=\"auto\">\u62e5\u6709\u5927\u91cf\u65b0\u529f\u80fd\u548c\u4f7f\u7528\u8d28\u91cf\u6539\u8fdb\uff0c\u91cd\u70b9\u662f<\/span><span data-contrast=\"auto\"> JSON <\/span><span data-contrast=\"auto\">\u67b6\u6784\u548c\u667a\u80fd\u5e94\u7528\u7a0b\u5e8f\u652f\u6301\u3002\u5728<\/span><span data-contrast=\"auto\"> .NET 9 <\/span><span data-contrast=\"auto\">\u5f00\u53d1\u671f\u95f4\uff0c\u5171\u6709<\/span> <a href=\"https:\/\/github.com\/dotnet\/runtime\/pulls?q=is:pr+is:merged+label:area-System.Text.Json+milestone:9.0.0\"><span data-contrast=\"auto\">46 <\/span><span data-contrast=\"none\">\u4e2a\u62c9\u53d6\u8bf7\u6c42<\/span><\/a><span data-contrast=\"auto\">\u4e3a<\/span><span data-contrast=\"auto\"> System.Text.Json <\/span><span data-contrast=\"auto\">\u505a\u51fa\u8d21\u732e\u3002\u6211\u4eec\u5e0c\u671b\u60a8\u5c1d\u8bd5\u65b0\u529f\u80fd\u5e76\u5411\u6211\u4eec\u63d0\u4f9b\u53cd\u9988\uff0c\u544a\u8bc9\u6211\u4eec\u5b83\u5982\u4f55\u6539\u8fdb\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u4ee5\u53ca\u60a8\u53ef\u80fd\u9047\u5230\u7684\u4efb\u4f55\u53ef\u7528\u6027\u95ee\u9898\u6216\u9519\u8bef<\/span><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">\u6211\u4eec\u968f\u65f6\u6b22\u8fce\u793e\u533a\u8d21\u732e\u3002\u5982\u679c\u60a8\u60f3\u4e3a<\/span><span data-contrast=\"auto\"> System.Text.Json <\/span><span data-contrast=\"auto\">\u505a\u51fa\u8d21\u732e\uff0c\u8bf7\u67e5\u770b\u6211\u4eec\u5728<\/span><span data-contrast=\"auto\"> GitHub <\/span><span data-contrast=\"auto\">\u4e0a\u7684<\/span><a href=\"https:\/\/github.com\/dotnet\/runtime\/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aarea-System.Text.Json\"><span data-contrast=\"none\">\u6c42\u52a9\u95ee\u9898\u5217\u8868<\/span><\/a><span data-contrast=\"auto\">\u3002<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p>\u5982\u679c\u60a8\u6709\u4efb\u4f55\u6280\u672f\u95ee\u9898\uff0c\u6b22\u8fce\u6765<a href=\"https:\/\/learn.microsoft.com\/zh-cn\/answers\/tags\/309\/csharp\" target=\"_blank\" rel=\"noopener\">Microsoft Q&amp;A<\/a>\u00a0\u63d0\u95ee\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u7bc7\u7ffb\u8bd1\u4e8eEirik Tsarpalis\u7684\u00a0What&#8217;s new in System.Text.Json in .NET 9 &#8211; .NET Blog\u00a0 System.Text.Json\u76849.0 \u7248\u672c\u5305\u542b\u8bb8\u591a\u529f\u80fd\uff0c\u4e3b\u8981\u4fa7\u91cd\u4e8e JSON \u67b6\u6784\u548c\u667a\u80fd\u5e94\u7528\u7a0b\u5e8f\u652f\u6301\u3002\u5b83\u8fd8\u5305\u62ec\u4e00\u4e9b\u5907\u53d7\u671f\u5f85\u7684\u589e\u5f3a\u529f\u80fd\uff0c\u4f8b\u5982\u53ef\u7a7a\u5f15\u7528\u7c7b\u578b\u652f\u6301\u3001\u81ea\u5b9a\u4e49\u679a\u4e3e\u6210\u5458\u540d\u79f0\u3001\u65e0\u5e8f\u5143\u6570\u636e\u53cd\u5e8f\u5217\u5316\u548c\u81ea\u5b9a\u4e49\u5e8f\u5217\u5316\u7f29\u8fdb\u3002\u00a0 \u83b7\u53d6\u6700\u65b0\u4fe1\u606f\u00a0 \u60a8\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528 System.Text.Json NuGet \u5305\u7684\u6700\u65b0\u7248\u672c\u6216 .NET 9 \u7684\u6700\u65b0 SDK \u6765\u5c1d\u8bd5\u65b0\u529f\u80fd\u3002\u00a0 JSON \u67b6\u6784\u5bfc\u51fa\u5668\u00a0 \u65b0\u7684 JsonSchemaExporter \u7c7b\u53ef\u4ee5\u4f7f\u7528 JsonSerializerOptions \u6216 JsonTypeInfo \u5b9e\u4f8b\u4ece .NET \u7c7b\u578b\u4e2d\u63d0\u53d6 JSON \u67b6\u6784\u6587\u6863\uff1a\u00a0 using System.Text.Json.Schema; JsonSerializerOptions options = JsonSerializerOptions.Default; JsonNode schema = options.GetJsonSchemaAsNode(typeof(Person)); Console.WriteLine(schema.ToString()); \/\/{ \/\/ &#8220;type&#8221;: [&#8220;object&#8221;, &#8220;null&#8221;], \/\/ [&hellip;]<\/p>\n","protected":false},"author":97248,"featured_media":838,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2,58],"class_list":["post-834","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet-ch","tag-net","tag-json"],"acf":[],"blog_post_summary":"<p>\u672c\u7bc7\u7ffb\u8bd1\u4e8eEirik Tsarpalis\u7684\u00a0What&#8217;s new in System.Text.Json in .NET 9 &#8211; .NET Blog\u00a0 System.Text.Json\u76849.0 \u7248\u672c\u5305\u542b\u8bb8\u591a\u529f\u80fd\uff0c\u4e3b\u8981\u4fa7\u91cd\u4e8e JSON \u67b6\u6784\u548c\u667a\u80fd\u5e94\u7528\u7a0b\u5e8f\u652f\u6301\u3002\u5b83\u8fd8\u5305\u62ec\u4e00\u4e9b\u5907\u53d7\u671f\u5f85\u7684\u589e\u5f3a\u529f\u80fd\uff0c\u4f8b\u5982\u53ef\u7a7a\u5f15\u7528\u7c7b\u578b\u652f\u6301\u3001\u81ea\u5b9a\u4e49\u679a\u4e3e\u6210\u5458\u540d\u79f0\u3001\u65e0\u5e8f\u5143\u6570\u636e\u53cd\u5e8f\u5217\u5316\u548c\u81ea\u5b9a\u4e49\u5e8f\u5217\u5316\u7f29\u8fdb\u3002\u00a0 \u83b7\u53d6\u6700\u65b0\u4fe1\u606f\u00a0 \u60a8\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528 System.Text.Json NuGet \u5305\u7684\u6700\u65b0\u7248\u672c\u6216 .NET 9 \u7684\u6700\u65b0 SDK \u6765\u5c1d\u8bd5\u65b0\u529f\u80fd\u3002\u00a0 JSON \u67b6\u6784\u5bfc\u51fa\u5668\u00a0 \u65b0\u7684 JsonSchemaExporter \u7c7b\u53ef\u4ee5\u4f7f\u7528 JsonSerializerOptions \u6216 JsonTypeInfo \u5b9e\u4f8b\u4ece .NET \u7c7b\u578b\u4e2d\u63d0\u53d6 JSON \u67b6\u6784\u6587\u6863\uff1a\u00a0 using System.Text.Json.Schema; JsonSerializerOptions options = JsonSerializerOptions.Default; JsonNode schema = options.GetJsonSchemaAsNode(typeof(Person)); Console.WriteLine(schema.ToString()); \/\/{ \/\/ &#8220;type&#8221;: [&#8220;object&#8221;, &#8220;null&#8221;], \/\/ [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/posts\/834","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/users\/97248"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/comments?post=834"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/posts\/834\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/media\/838"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/media?parent=834"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/categories?post=834"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet-ch\/wp-json\/wp\/v2\/tags?post=834"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}