C# Newtonsoft JsonSerializer未设置正确的类型
我有一个自定义包装,其外观如下所示:C# Newtonsoft JsonSerializer未设置正确的类型,c#,json.net,C#,Json.net,我有一个自定义包装,其外观如下所示: public class MySerializer { JsonSerializer serializer; public MySerializer() { serializer = new JsonSerializer { TypeNameHandling = TypeNameHandling.Auto, DefaultValueHandling =
public class MySerializer
{
JsonSerializer serializer;
public MySerializer()
{
serializer = new JsonSerializer
{
TypeNameHandling = TypeNameHandling.Auto,
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
ContractResolver = new DefaultContractResolver()
};
}
public byte[] Serialize<T>(T value)
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8))
serializer.Serialize(new JsonTextWriter(streamWriter), value);
return memoryStream.ToArray();
}
}
public T Deserialize<T>(byte[] serialized)
{
using (MemoryStream memoryStream = new MemoryStream(serialized))
{
using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8))
return serializer.Deserialize<T>( new JsonTextReader(streamReader));
}
}
}
public class Person
{
public House LivingArrangement { get; set; } = new TreeHouse();
}
public class House
{
public int NumberOfBeds { get; set; }
public virtual bool IsInTree => false; // just to show the issue
}
public class TreeHouse : House
{
public override bool IsInTree => true; // just to show the issue
}
在现实世界中要复杂得多,但这只是为了说明问题。请注意,如果没有其他设置,每个人都住在树屋中。这是非常重要的,不能因为我的项目中的其他限制而更改。初始化类时,必须将类型设置为TreeHouse。它不能为空
问题是,当类被反序列化时,类型是TreeHouse,即使我显式地将其设置为House。请参阅下面的测试
[TestMethod]
public void Serialization_Test()
{
var item = new Person();
item.LivingArrangement = new House(); // This person lives in a house.
item.LivingArrangement.NumberOfBeds = 2;
var serializer = new MySerializer();
var serializedItem = serializer.Serialize(item);
var deserializedItem = serializer.Deserialize<Person>(serializedItem);
Console.WriteLine(deserializedItem.LivingArrangement.GetType()); // Output: UnitTestProject1.TreeHouse
// Works fine!
Assert.IsTrue(item.LivingArrangement.NumberOfBeds == 2);
// The assert fails.
Assert.IsFalse(deserializedItem.LivingArrangement.IsInTree);
// The assert fails.
Assert.AreEqual(deserializedItem.LivingArrangement.GetType(), typeof(House));
}
为什么JsonSerializer保留TreeHouse而不是启动House的新实例?如何修复它,但仍然使用JsonSerializer?您必须设置一个附加属性ObjectCreationHandling: 现在,json中有了更多信息。 如果您将树屋设置为LivingArrange,那么您的JSON字符串在$type中包含类型信息
serializer = new JsonSerializer
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
ContractResolver = new DefaultContractResolver()
};