我需要Asp.net来使用特定的派生类反序列化对象的属性。
根据Newtonsoft的文档,我应该能够为基类Equipment.Shared.Model.SimCard更改JsonContract。 https://www.newtonsoft.com/json/help/html/ContractResolver.htm
Class Transmitter具有属性(Simcard) Equipment.Shared.Model.SimCard ,但是我需要将其反序列化为 TlsModel.SimCard ,否则为 TlsModel .SimCard 属性在反序列化过程中会被丢弃。
public class TlsModelContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
JsonContract contract = base.CreateContract(objectType);
if (objectType == typeof(Equipment.Shared.Model.SimCard) )
{
contract.CreatedType = typeof(SimCard);
Console.WriteLine("Simcard CreateType is updated");
}
return contract;
}
}
在第一次反序列化时,我的日志行为“ Simcard CreateType isupdated”,因此考虑了我的合同反硝化器。
但是,发射机。SimCard仍然是 Equipment.Shared.Model.SimCard ,而不是我认为的 TlsModel.SimCard 。
我错过了什么吗?
答案 0 :(得分:3)
还必须用适当的创建函数替换JsonContract.DefaultCreator
的值,如果基类没有公共构造函数,则可能设置JsonContract.DefaultCreatorNonPublic = false
:
public class TlsModelContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
JsonContract contract = base.CreateContract(objectType);
if (objectType == typeof(Equipment.Shared.Model.SimCard) )
{
contract.CreatedType = typeof(SimCard);
Debug.WriteLine("Simcard CreateType is updated");
contract.DefaultCreator = () => new SimCard();
contract.DefaultCreatorNonPublic = false;
}
return contract;
}
}
注意:
调用基本方法DefaultContractResolver.CreateContract()
后,合同已完全初始化,因此您需要手动进行所有更改。
如果您的SimCard
模型具有参数化构造函数,则需要覆盖DefaultContractResolver.CreateObjectContract
并更新CreatorParameters
和OverrideCreator
。
作为自定义合同解析器的替代方法,您可以引入一个SimCardConverter : CustomCreationConverter<Equipment.Shared.Model.SimCard>
,其Create()
方法返回一个new SimCard()
。
public class SimCardConverter : CustomCreationConverter<Equipment.Shared.Model.SimCard>
{
public override bool CanConvert(Type objectType) { return typeof(Equipment.Shared.Model.SimCard) == objectType; }
public override Equipment.Shared.Model.SimCard Create(Type objectType) { return new SimCard(); }
}
(如果您直接反序列化typeof(T) == objectType;
的任何派生类型,则可能还需要重写CustomCreationConverter<T>.CanConvert(Type objectType)
以返回typeof(T).IsAssignableFrom(objectType);
而不是Equipment.Shared.Model.SimCard
。)
演示小提琴here。
答案 1 :(得分:0)
如果您使用的是newtonsoft json,则可以按照以下说明使用(在序列化和反序列化类型下)类型名称处理来实现:https://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm
它只是将属性“ @type”添加到每个对象。
示例
请考虑以下课程:
//dll My.Dll
namespace My.Namespace
public class MyObj {
public string Name {get;set;}
public object Whatever {get;set;}
}
var objInner = new MyObj { Name = "Inner" };
var objOuter = new MyObj { Name = "Outer", Whatever = obj1 }
var jsonString = JsonConvert.SerializeObject(objOuter, Formatting.Indented, new
JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.Writeline(jsonString);
//produces
//{
// "@type": "My.Namespace.MyObj, My.Dll",
// "Name": "Outer",
// "Whatever": {
// "@type": "My.Namespace.MyObj, My.Dll",
// "Name": "Inner"
// }
//}
//to deserialize
var deserializedObj = JsonConvert.DserializeObject<MyObj>(objOuter, new
JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});