当前位置: 首页 > 面试题库 >

使用.NET Newtonsoft.Json组件反序列化某些有效json时,为什么POCO中的所有集合都为null

史懿轩
2023-03-14
问题内容

问题

当尝试使用Newtonsoft的Json.NET
nuget库反序列化某些Json时,如果我不提供JsonSerializerSettings-为什么?我的collection-
properties为null ?

细节

我有一些有效的json数据,并将其反序列化为我的自定义类/
POCO。现在,所有简单的属性(例如strings,int‘s等)都已正确设置。我的简单子类也已正确设置(例如,User属性或BuildingDetails属性等)。

我所有的收藏都是null。这些设置器永远不会被调用(我在其中设置了一个断点,但它们没有被设置,但是其他设置器却被调用/设置了)。

例如。属性。

List<Media> Images { get { ... } set { ... } }

例如。

var foo = new Foo();
var json = JsonConvert.Serialize(foo);
var anotherFoo = JsonConvert.Deserialize<Foo>(json);

// the collection properties on anotherFoo are null

现在-这是疯狂的事情:当我使用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);

我的收藏集已设定!

请注意:ObjectCreationHandling = ObjectCreationHandling.Replace。这是使事情正常进行的神奇设置。

这是什么做的?为什么 不能 有这个设置意味着我的收藏品都没有得到集/创建/等?

另一个线索。如果我 没有 二传手,则collection为null /未设置。如果我有这样的二传手,它也会失败:

public List<Media> Images
{
    get { return new List<Media> { new Media{..}, new Media{..} }; }
   set { AddImages(value); }
}

如果我不返回列表,则getter在集合中为SET!有用!

private List<Media> _images;
public List<Media> Images
{
    get { return _images; }
    set { AddImages(value); }
}

请注意,现在如何仅使用烘烤场?

就像集合的GETTER属性和结果之间存在一些奇怪的连接/关联,以及Json.net如何使用auto设置来设置此数据?


问题答案:

您的问题是,您要反序列化的属性在对象图中获取并设置了 代理
集合,而不是“真实”集合。这样做违反了Json.NET用于构造和填充返回参考类型对象,集合和词典的属性的算法的实现决策。该算法是:

  1. 它在父类中调用getter以获取要反序列化的属性的当前值。

  2. 如果为null,并且除非使用自定义构造函数,否则它将分配属性的返回类型的实例(使用该类型的JsonContract.DefaultCreator方法)。

  3. 它调用父级中的setter,以将分配的实例设置回父级中。

  4. 它将继续填充类型的实例。

  5. 实例填充后,它不会将实例再次设置回第二次。

在开始时调用getter可以填充类型的实例(例如使用JsonConvert.PopulateObject()),然后递归地填充该类型所引用的其他类型的任何预分配实例。(这就是中的existingValue参数的目的JsonConverter.ReadJson()。)

但是,以这种方式填充预分配的对象图的能力是有代价的:图中遇到的每个对象必须是 真实
对象,而不是为序列化目的创建的某些代理对象。如果getter返回的对象只是某个代理,则将填充该代理,而不填充“真实”对象-
除非该代理具有某种机制,以将对其数据的更改传递回其始发者。

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); }
}

对于数组,Json.NET(和XmlSerializer必须
在完全读取数组之后调用setter,因为在完全读取之前无法知道大小,因此无法分配数组并在完全读取之前将其设置回去。

(您也可以使用代理技巧ObservableCollection,但是我不推荐这样做。)



 类似资料:
  • 问题内容: 我在使用Jackson来反序列化JSON字符串时遇到问题(但是我没有问题将对象序列化为JSON)。 下面,我介绍我使用的类。当我接收到JSON字符串(已在其他地方进行序列化并通过Web服务检索的ProtocolContainer)并想反序列化时,就会出现问题: JSON字符串: {“ DataPacketJSONString”:null,“ DataPacketType”:“ MyPa

  • 问题内容: 我正在使用Ef 4.1,并且有一个POCO对象要序列化为JSON,我已经读到在使用延迟加载时这样做有问题,但是我不确定我可以这样做,因为一个可以的集合。 有什么办法吗?将这种对象序列化为JSON? 我的对象看起来像: 问题答案: 问题是循环引用。避免这种情况的一种简单方法是使用Json.Net http://james.newtonking.com/projects/json- net

  • 问题内容: 我正在为项目使用Typescript,需要将集合序列化为json,将其保存到文件中,然后将该文件反序列化为类似的集合。该集合看起来像: 我的工具界面如下所示: 工具实现如下所示: 我有一些工具界面的实现:textTool,imageTool和rectangleTool。我需要解决的问题是,当我将文件内容反序列化为工具集合时,我只会得到一个常规对象,而不是例如textTool的实例。 我

  • 问题内容: 当我尝试运行时,某些命令可以运行,而其他命令却可以执行,但是失败或执行与终端不同的操作。这是一个独立的测试案例,演示了这种效果: 如果将命令替换为echo hello world,该示例将非常有用,但是对于其他命令(尤其是那些涉及文件名且带有空格的命令),即使该命令显然正在执行,我也会出错: 同时,将其复制粘贴到我的shell中: 为什么有区别?它什么时候工作,什么时候失败?如何使它适

  • 问题内容: 我想知道如何让Jackson JSON库将JSON反序列化为现有对象?我试图找到如何做到这一点。但它似乎只能接受一个Class并实例化它本身。 或者,如果不可能,我想知道是否有任何Java JSON反序列化库都可以做到。 对于C#,这似乎是一个相应的问题:将数据从JSON字符串覆盖到现有对象实例。似乎JSON.NET具有PopulateObject(string,object)。 问题

  • 问题内容: 我正在尝试反序列化此JSON 我尝试使用Json.NET,并尝试使用ServiceStack的反序列化器,但似乎无法获得此JSON的任何类型的表示形式。 我认为阻止我的主要因素是键是Int,但是我无法控制收到的JSON。 这是我建立的C#类 我更喜欢使用ServiceStack,但是任何其他可以运行的反序列化器都将非常有用 var data = client.Get(json); 问题