Как десериализовать свойство объекта с помощью определенного производного класса c - PullRequest
3 голосов
/ 08 июля 2020

Мне нужно Asp. net для десериализации свойства объекта с помощью указанного c производного класса.

Согласно документации Newtonsoft, я должен иметь возможность изменить JsonContract для базового класса Equipment .Shared.Model.SimCard. 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 обновлена», поэтому мой контракт учитывается десерализатор.

Но передатчик.SimCard по-прежнему Equipment.Shared.Model.SimCard , а не TlsModel.SimCard , как я ожидал.

Я что-то пропустил?

Ответы [ 2 ]

3 голосов
/ 08 июля 2020

Вы также должны заменить значение JsonContract.DefaultCreator соответствующей функцией создания и, возможно, установить JsonContract.DefaultCreatorNonPublic = false, если у базового класса не было конструктора publi c :

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(); }
    }
    

    (вам также может потребоваться переопределить CustomCreationConverter<T>.CanConvert(Type objectType), чтобы вернуть typeof(T) == objectType;, а не typeof(T).IsAssignableFrom(objectType); если вы когда-нибудь напрямую десериализуете какие-либо производные типы Equipment.Shared.Model.SimCard.)

Демо-скрипт здесь .

0 голосов
/ 08 июля 2020

Если вы используете 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
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...