【问题标题】:How to deserialize an object's property with a specific derived class如何使用特定的派生类反序列化对象的属性
【发布时间】:2020-10-29 05:31:27
【问题描述】:

我需要 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 is updated',所以我的合约反序列化器被考虑在内。

但transmitter.SimCard 仍然是一个Equipment.Shared.Model.SimCard,而不是我预期的TlsModel.SimCard

我错过了什么吗?

【问题讨论】:

    标签: c# asp.net json json.net deserialization


    【解决方案1】:

    您还必须将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;
        }
    }
    

    注意事项:

    演示小提琴here.

    【讨论】:

    • 我有一个解析器解决方案的问题:派生类的属性没有反序列化,尽管创建了正确的类型。我更新了您在此处创建的小提琴:dotnetfiddle.net/d5Vi1s 在派生类上添加属性 SerialNumber。请你运行它看看会发生什么?
    • @AnthonyBrenelière - 我认为最好用正确的minimal reproducible example 提出另一个问题来证明问题。您六周前的原始问题似乎是关于对象构造,所以这就是答案所涵盖的内容。您可以检查上面小提琴中的CustomCreationConverter<Equipment.Shared.Model.SimCard> 是否巧合地解决了问题。或者至少编辑当前问题以阐明您的要求。
    • 我的问题从未改变,是关于在派生类和基类上具有属性的对象的反序列化。使用解析器的解决方案,添加了 DefaultCreator 可以很好地创建正确的类型,但是如果它的属性没有被反序列化,那有什么意义呢?你拉小提琴了吗dotnetfiddle.net/d5Vi1s?它表明它适用于 Converter 但不适用于 Resolver 解决方案。
    【解决方案2】:

    如果您使用的是 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
    });
    

    【讨论】:

    • json由不知道反序列化类型的API客户端序列化。我不能让客户端依赖于代码中使用的日期模型、类型和程序集名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多