Десериализация защищенного свойства в WebAPI равна нулю - PullRequest
0 голосов
/ 08 апреля 2020

Мое решение имеет проект WebAPI (. net core 3.1, Microsoft.AspNetCore. Mvc) и библиотеку классов (. Net Standard 2.1), которая определяет структуры данных. Мой контроллер принимает сообщение с единственным параметром, который десериализуется в основном корректно


public class apiRequest
{
    public RequestData TheData { get; set; }
    public Options Options { get; set; }
    public apiRequest() { }
}

Объекты RequestData и дочерние объекты определены, например,. Net Стандартная библиотека классов 2.1 и добавлены через пакет nuget


public class RequestData : IRequestData
{
    public int Datum{ get; set; }
    ...
    public List<ComplexItem> ComplexItems { get; set; }
    ...
}
public class ComplexItem: ItemBase, IComplexItem
{
    public ComplexItem() : base() { }
    public ComplexItem(Pricing defaultPricing) : base(defaultPricing) { }
    [JsonConstructor]
    public ComplexItem(Pricing defaultPricing, Pricing selectedPricing) : base(defaultPricing, selectedPricing) { }
}

Проблема, с которой я сталкиваюсь, заключается в том, что defaultPricing всегда равен нулю, когда он попадает в контроллер


public class ItemBase : IItemBase
{
    public ItemBase () { }
    public ItemBase (Pricing defaultPricing)
    {
        DefaultPricing = defaultPricing;
    }
    [JsonConstructor]
    public ItemBase (Pricing defaultPricing, Pricing selectedPricing)
    {
        DefaultPricing = defaultPricing;
        SelectedPricing = selectedPricing;
    }

    #region Pricing
    [JsonProperty]
    protected Pricing DefaultPricing { get; set; }
    public Pricing SelectedPricing { get; set; }
    [JsonIgnore]
    protected Pricing CurrentPricing
    {
        get { return SelectedPricing ?? DefaultPricing; }
        set { SelectedPricing = value; }
    }
    [JsonIgnore]
    public decimal Cost { get => CurrentPricing?.Cost ?? 0; }
    [JsonIgnore]
    public decimal Price { get => CurrentPricing?.Price ?? 0; }
    #endregion
}

I пробовал использовать атрибуты [DataContract] и [DataMember], атрибуты JsonObject, JsonConstructor, JsonProperty и атрибут [Serializable]. (Существуют ли в настоящее время лучшие рекомендации по использованию?)

Если я прочитал Json из файла и использую Newtonsoft. Json .JsonConvert.DeserializeObject, он десериализовался правильно с добавленными атрибутами Json , но все еще null в контроллере.

Он также десериализуется в API должным образом, если я сделаю его public c, так что это не выглядит проблемой в самом классе Pricing

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

System.Text. Json Сериализует Publi c Свойства

Как документация подразумевает (выделение моя) :

По умолчанию все (только для чтения) publi c свойства сериализуются. Вы можете указать свойства для исключения.

Я бы предположил, что это был дизайн, выбранный, потому что сериализация объекта позволяет этому объекту пересекать барьеры области видимости, и только область действия publi c можно с уверенностью предположить.

Если подумать, это имеет смысл. Допустим, вы определяете свойство protected и сериализуете объект. Затем клиент берет его и десериализует это текстовое представление в свойство public. То, что вы спроектировали как деталь реализации / для производных типов, теперь доступно за пределами области, определенной модификатором.

Помимо простого указания вашего собственного ответа, где Newtonsoft позволяет этому защищенному свойству быть Я бы посоветовал вам более пристально взглянуть на свой дизайн и почему эти свойства защищены в первую очередь. Это имеет смысл в контексте вашей реализации API, но нельзя предположить (не следует), что клиент следует той же структуре наследования (или вообще поддерживает наследование). Кажется, что вы, возможно, захотите определить истинный DTO, который будет действовать как «форма» вашего ответа API, и найти подходящее место для перехода от ваших внутренних типов, используя область действия protected для контроля доступа и DTO, который может пересекать границу API.

0 голосов
/ 08 апреля 2020

После публикации я нашел этот Вопрос о том, чтобы сделать Newtonsoft по умолчанию и использовать MikeBeaton's принятое там решение с Microsoft.AspNetCore. Mvc .Newtonsoft Json пакет работал так, что я ' Я поставлю это как один потенциальный ответ для любого другого с этой проблемой. Все еще хотел бы знать, если есть более правильное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...