目前我正在尝试在我的项目中使用Json.Net序列化程序。
我遇到的一个问题是,反序列化的对象会获取所有重复的私有列表项。 它可以像这样再现:
private
类型的List<>
字段创建类,其中List<>
泛型参数是其他类public
属性,获取/设置private
字段重现问题的代码:
public class ClassParam
{
public int? ParamOne
{
get;
set;
}
}
public class ClassWithParams
{
private List<ClassParam> _privateFieid = new List<ClassParam>();
public List<ClassParam> PropertWithBackingField
{
get { return _privateFieid; }
set { _privateFieid = value; }
}
public void AddElementToPrivateField(ClassParam classParam)
{
_privateFieid.Add(classParam);
}
}
[Test]
public void Test()
{
var instance = new ClassWithParams();
var param1 = new ClassParam { ParamOne = 1 };
instance.PropertWithBackingField.Add(param1);
var contractResolver = new DefaultContractResolver();
contractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic;
string serializedInstance = JsonConvert.SerializeObject(instance,
Formatting.Indented,
new JsonSerializerSettings()
{
ContractResolver = contractResolver
});
var deserializeInstance = JsonConvert.DeserializeObject(serializedInstance, typeof(ClassWithParams),
new JsonSerializerSettings()
{
ContractResolver = contractResolver
});
}
1 http://s019.radikal.ru/i619/1209/7a/e342f5f5b97e.png
当我从PropertWithBackingField
删除公共财产ClassWithParams
时,一切正常。
当我不使用ContractResolver的自定义设置时,问题也消失了。但是,一旦并非所有类的私有数据都通过公共属性公开,我确实需要序列化我的类的私有数据。
我的代码出了什么问题?使用Json.Net是否有任何细微之处,还是一个bug?
答案 0 :(得分:1)
对于此代码
var s = JsonConvert.SerializeObject(instance);
var desInst = JsonConvert.DeserializeObject<ClassWithParams>(s);
你的json将是{"PropertWithBackingField":[{"ParamOne":1}]}
但是你说要用
包含序列化/反序列化中的私有字段contractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic;
并获得一个json
{
"_privateFieid": [
{
"ParamOne": 1
}
],
"PropertWithBackingField": [
{
"ParamOne": 1
}
]
}
因此,有两个反序列化,一个用于_privateFieid
,另一个用于PropertWithBackingField
使用BindingFlags.Public
或使用上面的代码更简单。
答案 1 :(得分:-2)
DeserializeInstance
方法接收现有实例作为参数。可能它不会创建新实例但会填充现有实例并将其返回。
尝试将ReferenceEquals(instance, deserializedInstance)
放到手表上。为避免数据重复,请使用不接受现有实例的重载或创建新实例并对其进行反序列化。