.NET JsonSerializer无法序列化元组的值。

10

JSON序列化器返回一个空的JSON对象。

using System.Text.Json;

(int, int) tuple1 = (1, 2);
var token = JsonSerializer.Serialize(tuple1); // return empty object {}

(int item1, int item2) tuple2 = (1, 2);
token = JsonSerializer.Serialize(tuple2); // return empty object {}

(int item1, int item2) tuple3 = (item1:1, item2:2);
token = JsonSerializer.Serialize(tuple3); // return empty object {}

通过多种解决方法可以传递它

我正在尝试理解为什么或者有什么阻止序列化程序理解元组

与元组的结构是否有关


1
为什么要使用元组?你期望得到什么?ValueTuple没有属性,只有公共字段。这些字段被命名为Item1Item2等。 - Panagiotis Kanavos
2
https://github.com/dotnet/runtime/issues/31004 - Daniel A. White
我觉得有趣的是序列化器使用更明确的 Tuple<int,int>,并具有属性 Item1Item2 - TJ Rockefeller
@TJRockefeller 那些是类,它们实际上有属性。值元组则没有。 - Daniel A. White
1
@TJRockefeller,它不是更明确,而是完全不同。Tuple<int,int>是一种具有属性的引用类型(int,int)是一个ValueTuple,它是一个带有字段的结构体。串行器默认使用属性,因为字段通常是实现细节。 - Panagiotis Kanavos
@PanagiotisKanavos,这很好知道,我一直以为值元组只是语法糖,基本上是Tuple的别名。 - TJ Rockefeller
2个回答

17

ValueTuple没有属性,只有公共字段。直到.NET 6,System.Text.Json才会序列化公共属性。这是最常见的情况,因为字段被认为是实现而不是对象API的一部分。所有的序列化器都优先考虑属性而不是字段,除非指示也序列化字段。

.NET 6 添加了序列化字段的能力,与其他序列化器类似,可以使用字段上的属性或序列化器设置来进行序列化。

由于我们无法向元组字段添加属性,因此我们可以使用设置:

var options = new JsonSerializerOptions
{
    IncludeFields = true,
};
var json = JsonSerializer.Serialize(tuple1, options);

这会产生:
 {"Item1":1,"Item2":2}

3

如果有人关心反序列化,而且你有一个包含元组的更复杂的类,请注意以下内容。

public class Foo
{
    public (string key, string value) Tuple1{ get; set; }
}

var options = new JsonSerializerOptions
{
    IncludeFields = true,
};

string jsonString = File.ReadAllText("myconfig.json");
Foo obj1 = JsonSerializer.Deserialize<Foo>(jsonString, options);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接