Установщик свойства в Json десериализации для списка <Bar> - PullRequest
3 голосов
/ 01 апреля 2020

В System.Text. Json как работает «установщик» при использовании свойств типа List? это не так, как я ожидал, особенно в отношении установщика для строки в качестве примера.

Вот что я имею в виду:

public class Program
{
    public static void Main()
    {
        var json = @"
            {
              ""doot"": ""bloop bloop"",
              ""bars"": 
              [
                {
                    ""id"": 1
                },
                {
                    ""id"": 2
                }
              ]
            }
        ";

        var obj = JsonSerializer.Deserialize<Foo>(json);
        Console.WriteLine($"obj.Doot: {obj.Doot}");

        if (obj.Bars == null)
            Console.WriteLine("Bars is null.");
        else
            Console.WriteLine($"obj.Bars.Count: {obj.Bars.Count}");

    }

    public class Foo
    {
        private string _doot;
        [JsonPropertyName("doot")]
        public string Doot
        {
            get => _doot;
            set
            {
                Console.WriteLine($"Setting Doot to {value}");
                _doot = value;
            }
        }

        private List<Bar> _bars;
        [JsonPropertyName("bars")]
        public List<Bar> Bars 
        {
            get => _bars;
            set
            {
                Console.WriteLine($"Bars Value count during setter: {value.Count}");
                _bars = value;
            }
        }
    }
    public class Bar
    {
        [JsonPropertyName("id")]
        public int Id {get;set;}
    }
}

output:

Настройка Doot на bl oop bl oop

Бары Счетчик значений во время установки: 0

obj.Doot: bl oop bl oop

obj .Bars.Count: 2

В приведенном выше примере, когда срабатывает сеттер Doot, значение value устанавливается равным полю поддержки _doot. Когда срабатывает сеттер Bars, value содержит что-то , но это не два экземпляра Bar, как показано оператором Console.WriteLine в сеттере, который сообщает счетчик 0 .

Если мне нужно было сделать несколько логи c на основе значений, установленных в свойстве Bars, как я могу сделать sh, если value не имеет информации?

скрипка для справки:

https://dotnetfiddle.net/7z2O9S

РЕДАКТИРОВАТЬ:

это было указано мне в другом месте (если вы здесь спасибо), что список, вероятно, инициализируется как пустой список, тогда list.Add или list.AddRange могут быть использованы после инициализации (я неясно, что используется под прикрытием System.Text. Json); Это означает, что установщик будет выполнен только один раз, если я не изменю ссылку на список. Это имеет смысл, но, тем не менее, как мне подключиться к запуску некоторой логики c всякий раз, когда изменяется коллекция Bars?

1 Ответ

1 голос
/ 02 апреля 2020

Предположение в вашем редакторе верное. Способ десериализации списка заключается в том, что сначала создается объект списка, а затем добавляются отдельные элементы. Если вы думаете о том, как работает JSON, то для парсера и десериализатора имеет смысл работать следующим образом:

Когда парсер встречает [, он знает, что запускается массив JSON. Поэтому, когда этот объект должен быть десериализован в тип коллекции. NET, он может уже создать эту коллекцию в этот момент. В конце концов, десериализатор знает тип цели, до которого он должен десериализоваться.

Таким образом, десериализатор создает объект списка, а затем начинает десериализацию элементов внутри. В вашем случае это Bar объекты. Таким образом, он создает их, устанавливает свойства и, как только объект завершается, наконец добавляет их в список.

Вы действительно можете увидеть это в источнике. Существует несколько конвертеров коллекций, в зависимости от того, какой у вас целевой тип, но все они наследуются от IEnumerableDefaultConverter, который в основном имеет поведение, которое я описал выше . Для List<T> фактическая работа происходит в ListOfTConverter, который в основном просто инициализирует новый список и вызывает Add для каждого элемента.

Если мне нужно было сделать некоторые логики c на основе значений, установленных в свойстве Bars, как я могу сделать sh, что если значение не имеет информации?

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

...