我有一个JsonSerializer
的自定义包装器,它看起来像这样:
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));
}
}
}
由于项目的限制,它通常可以正常使用确实需要来使用JsonSerializer
。我不是在寻找任何其他序列化器。
我要序列化/反序列化的类看起来像这样:
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
}
在现实世界中,它要复杂得多,但这只是为了说明问题。请注意,如果未设置任何其他内容,则Person
每个TreeHouse
都会生成TreeHouse
。这非常重要,由于我的项目中的其他限制,无法更改。在启动类时,必须将类型设置为null
。它不能是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
而不是发起{{1}}的新实例?我该如何修复它,但仍然使用JsonSerializer?
答案 0 :(得分:1)
您必须设置其他属性ObjectCreationHandling
:
serializer = new JsonSerializer
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
ContractResolver = new DefaultContractResolver()
};
现在您在json中有更多信息。
如果您将TreeHouse
设置为LivingArrangement
,则您的JSON-String中包含类型信息($type
)。