问题描述
我是跟踪一个bug,我注意到,Newtonsoft JSON将追加资料转移到列表与LT;>
一个已经在默认的构造函数初始化。我做了一个小挖更与一些人对C#的聊天讨论,我们注意到,这种行为并不适用于所有其他集合类型。
I was tracking down a bug and I noticed that Newtonsoft JSON will append items to a List<>
that's been initialized in the default constructor. I did a little more digging and discussed with some people on the C# chat and we noticed that this behavior doesn't apply to all other collection types.
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Collections.ObjectModel;
public class TestClass
{
public Collection<string> Collection = new Collection<string>(new [] { "ABC", "DEF" });
public List<string> List = new List<string>(new [] { "ABC", "DEF" });
public ReadOnlyCollection<string> ReadOnlyCollection = new ReadOnlyCollection<string>(new [] { "ABC", "DEF" });
}
public class Program
{
public static void Main()
{
var serialized = @"{
Collection: [ 'Goodbye', 'AOL' ],
List: [ 'Goodbye', 'AOL' ],
ReadOnlyCollection: [ 'Goodbye', 'AOL' ]
}";
var testObj = JsonConvert.DeserializeObject<TestClass>(serialized);
Console.WriteLine("testObj.Collection: " + string.Join(",", testObj.Collection));
Console.WriteLine("testObj.List: " + string.Join(",", testObj.List));
Console.WriteLine("testObj.ReadOnlyCollection: " + string.Join(",", testObj.ReadOnlyCollection));
}
}
输出:
Output:
testObj.Collection: ABC,DEF
testObj.List: ABC,DEF,Goodbye,AOL
testObj.ReadOnlyCollection: Goodbye,AOL
正如你所看到的收藏<>
属性是反序列化的影响,在列表与LT;>
追加到和 ReadOnlyCollection还<>
将被替换。这是预期的行为?究竟是什么道理
As you can see the Collection<>
property is unaffected by deserialization, the List<>
is appended to and ReadOnlyCollection<>
is replaced. Is this intended behavior? What was the reasoning?
推荐答案
这基本上可以归结为输入实例和的设置。没有关于 ObjectCreationHandling
It basically boils down to type instantiation and the ObjectCreationHandling
setting. There are three settings for ObjectCreationHandling
自动0重用现有对象,创建新的对象三种设置在需要的时候。结果
再用1只重用现有的对象。结果
更换2始终创建新对象。
默认为汽车
()。
汽车只有经过一系列的确定当前的类型有检查覆盖一个 TypeInitializer
这是空。在这一点上它检查是否有参数的构造函数。
Auto is only overwritten after a series of checks which determine if the current type has a TypeInitializer
which is null. At that point it checks if there is a parameterless constructor.
///结果,
///创建可用于创建记载的JsonConverter的实例的工厂功能由结果
///参数类型。结果,
///返回的功能可以被用来或者调用转换器的默认构造函数,或者任何结果,
/ //参数的构造函数对象数组方式。结果
///
从本质上讲,它就像这样( 。它看起来像在6个班约1500行代码)
Essentially it acts like this (what it looks like is about 1500 lines of code in 6 classes).
ObjectCreationHandling och = ObjectCreationHandling.Auto;
if( typeInitializer == null )
{
if( parameterlessConstructor )
{
och = ObjectCreationHandling.Reuse;
}
else
{
och = ObjectCreationHandling.Replace;
}
}
这设置从而形成由JsonSerializerSettings的一部分里面DeserializeObject访问者模式构造。如上图所示,每个设置具有不同的功能。
This setting is a part of the JsonSerializerSettings which are composed inside of the visitor pattern constructor for DeserializeObject. As shown above, each setting has a different function.
让我们回到列表,收集和ReadOnlyCollection还,我们将看看在设定每个条件语句。
Getting back to List, Collection, and ReadOnlyCollection, we will look at the set of conditional statements for each.
列表的
testObj.List.GetType()。 TypeInitializer == NULL
是假的。其结果是,列表
接收默认ObjectCreationHandling.Auto并为testObj实例的初始化列表反序列化过程中使用,以及一个新的列表正在与<$ C实例。$ C>连载字符串
testObj.List.GetType().TypeInitializer == null
is false. As a result, List
receives the default ObjectCreationHandling.Auto and the instantiated List for the testObj instance is used during deserialization, as well as a new List being instantiated with the serialized
string.
testObj.List: ABC,DEF,Goodbye,AOL
的收藏的
testObj.Collection.GetType()。TypeInitializer == NULL
为真表示,没有反映类型初始可用,所以我们去下一个条件是要检查是否有参数的构造函数。 testObj.Collection.GetType()。GetConstructor(Type.EmptyTypes)== NULL
是假的。结果收藏
接收ObjectCreationHandling.Reuse的值(只重用现有的对象的)。为收集实例化的实例是从testObj使用,但连载
字符串不能被实例化。
testObj.Collection.GetType().TypeInitializer == null
is true indicating there was no reflected type initializer available, so we go to the next condition which is to check if there is a parameterless constructor. testObj.Collection.GetType().GetConstructor(Type.EmptyTypes) == null
is false. As a result Collection
receives the value of ObjectCreationHandling.Reuse (only reuse existing objects). The instantiated instance for Collection is used from testObj, but the serialized
string is not able to be instantiated.
testObj.Collection: ABC,DEF
的 ReadOnlyCollection还
testObj.ReadOnlyCollection.GetType()。TypeInitializer == NULL
为真表示,没有反映类型初始化可用,所以我们去下一个条件是要检查是否有参数的构造函数。 testObj.ReadOnlyCollection.GetType()。GetConstructor(Type.EmptyTypes)== NULL
也是如此。因此ReadOnlyCollection还临危ObjectCreationHandling.Replace的值(总是创建新的对象的)。只使用从连载
字符串初始化值。
testObj.ReadOnlyCollection.GetType().TypeInitializer == null
is true indicating there was no reflected type initializer available, so we go to the next condition which is to check if there is a parameterless constructor. testObj.ReadOnlyCollection.GetType().GetConstructor(Type.EmptyTypes) == null
is also true. As a result ReadOnlyCollection recieves the value of ObjectCreationHandling.Replace (always create new objects). Only the instantiated value from the serialized
string is used.
testObj.ReadOnlyCollection: Goodbye,AOL
这篇关于说明使用JSON Newtonsoft ObjectCreationHandling?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!