当尝试使用Newtonsoft的Json.NET nuget库反序列化某些Json时,如果我不提供JsonSerializerSettings-为什么?我的collection-properties为null ?
我有一些有效的json数据,并将其反序列化为我的自定义类/ POCO。现在,所有简单的属性(例如strings,int's等)都已正确设置。我的简单子类也已正确设置(例如,User属性或BuildingDetails属性等)。
我所有的收藏都是null。这些设置器永远不会被调用(我在其中设置了一个断点,但它们没有被设置,但是其他设置器却被调用/设置了)。
例如。属性。
List<Media> Images { get { ... } set { ... } }
Run Code Online (Sandbox Code Playgroud)
例如。
var foo = new Foo();
var json = JsonConvert.Serialize(foo);
var anotherFoo = JsonConvert.Deserialize<Foo>(json);
// the collection properties on anotherFoo are null
Run Code Online (Sandbox Code Playgroud)
现在-这是疯狂的事情:当我使用a时,JsonSerializerSettings它现在可以工作:
// NOTE: ModifiedDataContractResolver <-- skips any property that is a type
/ ModifiedData (which is a simple custom class I have).
var settings = new JsonSerializerSettings
{
ContractResolver = new ModifiedDataContractResolver(),
ObjectCreationHandling = ObjectCreationHandling.Replace,
Formatting = Formatting.Indented
};
var foo = new Foo();
var json = JsonConvert.Serialize(foo, settings);
var anotherFoo = JsonConvert.Deserialize<Foo>(json, settings);
Run Code Online (Sandbox Code Playgroud)
我的收藏集已设定!
请注意:ObjectCreationHandling = ObjectCreationHandling.Replace。这是使事情正常进行的神奇设置。
这是什么做的?为什么不能有这个设置意味着我的收藏品都没有得到集/创建/等?
另一个线索。如果我没有二传手,则collection为null /未设置。如果我有这样的二传手,它也会失败:
public List<Media> Images
{
get { return new List<Media> { new Media{..}, new Media{..} }; }
set { AddImages(value); }
}
Run Code Online (Sandbox Code Playgroud)
如果我不返回列表,则getter在集合中为SET!有用!
private List<Media> _images;
public List<Media> Images
{
get { return _images; }
set { AddImages(value); }
}
Run Code Online (Sandbox Code Playgroud)
请注意,现在如何仅使用烘焙字段?
就像集合的GETTER属性和结果之间存在一些奇怪的连接/关联,以及Json.net如何使用auto设置来设置此数据?
您的问题是,您要反序列化的属性在对象图中获取并设置了代理集合,而不是“真实”集合。这样做违反了Json.NET用于构造和填充返回参考类型对象,集合和字典的属性的算法的实现决策。该算法是:
它调用父类中的getter来获取要反序列化的属性的当前值。
如果为null,并且除非使用自定义构造函数,否则它将分配属性的返回类型的实例(使用该类型的JsonContract.DefaultCreator方法)。
它调用父级中的setter,以将分配的实例设置回父级中。
它将继续填充类型的实例。
实例填充后,它不会将实例再次设置回第二次。
在开始时调用getter可以填充类型的实例(例如JsonConvert.PopulateObject()),然后递归地填充该类型所引用的其他类型的任何预分配实例。(这就是中existingValue参数的目的JsonConverter.ReadJson()。)
但是,以这种方式填充预分配的对象图的能力是有代价的:图中遇到的每个对象必须是真实对象,而不是为序列化目的创建的某些代理对象。如果由getter返回的对象只是某个代理,则将填充该代理,而不填充“真实”对象-除非该代理具有某种机制,以将对其数据的更改传递回其始发者。
(虽然这个决定似乎是不合需要的,但这并不罕见;XmlSerializer 以相同的方式工作。有关执行此操作的序列化程序的列表,请参见具有代码默认值的XML集合属性的反序列化。)
ObjectCreationHandling = ObjectCreationHandling.Replace如您所见,更改了该算法,以便对集合进行分配,填充和设置。这是启用代理集合反序列化的一种方法。
作为另一个解决方法,您可以选择序列化和反序列化代理数组:
[JsonIgnore]
public List<Media> Images
{
get { return new List<Media> { new Media{..}, new Media{..} }; }
set { AddImages(value); }
}
[JsonProperty("Images")] // Could be private
Media [] ImagesArray
{
get { return Images.ToArray(); }
set { AddImages(value); }
}
Run Code Online (Sandbox Code Playgroud)
对于数组,Json.NET(和XmlSerializer)必须在完全读取数组后调用setter,因为要等到完全读取后才能知道大小,因此要分配数组,并要等到完全读取后才能将其设置回去。
(您也可以使用代理技巧ObservableCollection,但是我不推荐这样做。)
| 归档时间: |
|
| 查看次数: |
376 次 |
| 最近记录: |