属性 setter Json 反序列化列表 <Bar>
Property setter within Json deserialization for a List<Bar>
在 System.Text.Json 中,“setter”在使用列表类型的属性时如何工作?这不是我所期望的,尤其是与 setter 相关的字符串示例。
我的意思是:
public class Program
{
public static void Main()
{
var json = @"
{
""doot"": ""bloop bloop"",
""bars"":
[
{
""id"": 1
},
{
""id"": 2
}
]
}
";
var obj = JsonSerializer.Deserialize<Foo>(json);
Console.WriteLine($"obj.Doot: {obj.Doot}");
if (obj.Bars == null)
Console.WriteLine("Bars is null.");
else
Console.WriteLine($"obj.Bars.Count: {obj.Bars.Count}");
}
public class Foo
{
private string _doot;
[JsonPropertyName("doot")]
public string Doot
{
get => _doot;
set
{
Console.WriteLine($"Setting Doot to {value}");
_doot = value;
}
}
private List<Bar> _bars;
[JsonPropertyName("bars")]
public List<Bar> Bars
{
get => _bars;
set
{
Console.WriteLine($"Bars Value count during setter: {value.Count}");
_bars = value;
}
}
}
public class Bar
{
[JsonPropertyName("id")]
public int Id {get;set;}
}
}
输出:
Setting Doot to bloop bloop
Bars Value count during setter: 0
obj.Doot: bloop bloop
obj.Bars.Count: 2
在上面,当 Doot
setter 触发时,value
的值被设置为支持字段 _doot
。当 Bars
setter 触发时,value
中有 something,但不是两个 Bar
实例,如下所示setter 中的 Console.WriteLine
语句报告计数为 0。
如果我需要根据 属性 Bars
中设置的值做一些逻辑,如果 value
没有信息,我该如何实现?
fiddle供参考:
https://dotnetfiddle.net/7z2O9S
编辑:
有人在别处向我指出(caschw 如果你在这里谢谢)列表可能被初始化为一个空列表,然后 list.Add
或 list.AddRange
可以在初始化后使用(我不清楚在 System.Text.Json) 的掩护下使用的是哪个);这意味着 setter 只会执行一次,除非我更改对列表的引用。这是有道理的,但是,每当 Bars
的集合发生变化时,我将如何连接到 运行 一些逻辑?
您编辑中的假设是正确的。列表反序列化的方式是首先创建列表对象,然后添加各个元素。如果您考虑 JSON 是如何工作的,那么解析器和反序列化器以这种方式工作是有意义的:
当解析器遇到 [
时,它知道正在启动 JSON 数组。因此,当该对象要反序列化为 .NET 集合类型时,它此时已经可以创建该集合。毕竟,反序列化器知道它应该反序列化到的目标类型。
所以反序列化器创建了列表对象,然后开始反序列化里面的项目。在您的例子中,这些是 Bar
个对象。所以它构造那些,设置属性,并且——一旦对象完成——最终将它们添加到列表中。
您实际上可以在源代码中看到这一点。有许多集合转换器,具体取决于您拥有的目标类型,但它们都继承自 IEnumerableDefaultConverter
,后者基本上具有 the behavior I described above. For List<T>
, the actual work then happens in the ListOfTConverter
,它基本上只是初始化一个新列表并为每个调用 Add
项目。
If I needed to do some logic based on the values being set within the property Bars, how can I accomplish that if value does not have the information?
我认为你不应该。您应该将反序列化过程视为一个单独的操作,而不是对其进行干扰。我建议你之后再做,例如作为反序列化后的 post 处理步骤。
在 System.Text.Json 中,“setter”在使用列表类型的属性时如何工作?这不是我所期望的,尤其是与 setter 相关的字符串示例。
我的意思是:
public class Program
{
public static void Main()
{
var json = @"
{
""doot"": ""bloop bloop"",
""bars"":
[
{
""id"": 1
},
{
""id"": 2
}
]
}
";
var obj = JsonSerializer.Deserialize<Foo>(json);
Console.WriteLine($"obj.Doot: {obj.Doot}");
if (obj.Bars == null)
Console.WriteLine("Bars is null.");
else
Console.WriteLine($"obj.Bars.Count: {obj.Bars.Count}");
}
public class Foo
{
private string _doot;
[JsonPropertyName("doot")]
public string Doot
{
get => _doot;
set
{
Console.WriteLine($"Setting Doot to {value}");
_doot = value;
}
}
private List<Bar> _bars;
[JsonPropertyName("bars")]
public List<Bar> Bars
{
get => _bars;
set
{
Console.WriteLine($"Bars Value count during setter: {value.Count}");
_bars = value;
}
}
}
public class Bar
{
[JsonPropertyName("id")]
public int Id {get;set;}
}
}
输出:
Setting Doot to bloop bloop
Bars Value count during setter: 0
obj.Doot: bloop bloop
obj.Bars.Count: 2
在上面,当 Doot
setter 触发时,value
的值被设置为支持字段 _doot
。当 Bars
setter 触发时,value
中有 something,但不是两个 Bar
实例,如下所示setter 中的 Console.WriteLine
语句报告计数为 0。
如果我需要根据 属性 Bars
中设置的值做一些逻辑,如果 value
没有信息,我该如何实现?
fiddle供参考:
https://dotnetfiddle.net/7z2O9S
编辑:
有人在别处向我指出(caschw 如果你在这里谢谢)列表可能被初始化为一个空列表,然后 list.Add
或 list.AddRange
可以在初始化后使用(我不清楚在 System.Text.Json) 的掩护下使用的是哪个);这意味着 setter 只会执行一次,除非我更改对列表的引用。这是有道理的,但是,每当 Bars
的集合发生变化时,我将如何连接到 运行 一些逻辑?
您编辑中的假设是正确的。列表反序列化的方式是首先创建列表对象,然后添加各个元素。如果您考虑 JSON 是如何工作的,那么解析器和反序列化器以这种方式工作是有意义的:
当解析器遇到 [
时,它知道正在启动 JSON 数组。因此,当该对象要反序列化为 .NET 集合类型时,它此时已经可以创建该集合。毕竟,反序列化器知道它应该反序列化到的目标类型。
所以反序列化器创建了列表对象,然后开始反序列化里面的项目。在您的例子中,这些是 Bar
个对象。所以它构造那些,设置属性,并且——一旦对象完成——最终将它们添加到列表中。
您实际上可以在源代码中看到这一点。有许多集合转换器,具体取决于您拥有的目标类型,但它们都继承自 IEnumerableDefaultConverter
,后者基本上具有 the behavior I described above. For List<T>
, the actual work then happens in the ListOfTConverter
,它基本上只是初始化一个新列表并为每个调用 Add
项目。
If I needed to do some logic based on the values being set within the property Bars, how can I accomplish that if value does not have the information?
我认为你不应该。您应该将反序列化过程视为一个单独的操作,而不是对其进行干扰。我建议你之后再做,例如作为反序列化后的 post 处理步骤。