Могу ли я рассчитывать на порядок чтения узлов через JsonSerializer? - PullRequest
0 голосов
/ 18 сентября 2018

Я прочитал здесь Сохранен ли порядок элементов в списке JSON?

, что порядок в Json имеет значение .

Я также читал здесь Гарантирует ли List порядок вставки? что порядок вставки в общем списке C # гарантирован .

Могу ли я предположить, чтокогда я использую newtonsoft JsonSerializer, чтобы прочитать этот Json

 "answers": [
            {
                "choice": "36"
            },
            {
                "choice": "50"
            }
        ]

в объекте со свойством 'тип ответов', имеющим тип GenericList, этот тип ответа [0] всегда возвращает 36, а ответ [1] всегда возвращает 50?

Или, возможно, JsonSerializer перетасовывает данные?

Причина, по которой я спрашиваю, заключается в том, что я читаю данные из внешнего API и они говорят: «Вы должны получить только 1 ответ, но когдаВы получаете больше, используйте последний ", и последний является последним в тексте, так что в этом случае '50'.

1 Ответ

0 голосов
/ 02 октября 2018

Да, вы можете положиться на порядок узлов массива, считанных через JsonSerializer. Массив JSON определен как упорядоченный набор значений . , и Json.NET добавит их в вашу коллекцию в том порядке, в котором они встречаются в файле JSON.

Это можно проверить, проверив исходный код . Метод JsonSerializerInternalReader.CreateList() является методом верхнего уровня, отвечающим за десериализацию коллекции, и имеет три основных случая:

  1. При десериализации в коллекцию для чтения / записи, ICollection.Add() (или ICollection<T>.Add()) будет вызываться в порядке, в котором значения считываются из потока JSON, сохраняя тем самым порядок массива JSON. Это можно увидеть в JsonSerializerInternalReader.PopulateList().

    (Когда в коллекции отсутствует неуниверсальный метод Add(object value), создается CollectionWrapper<T> для обработки приведения к требуемому типу аргумента, однако это никак не влияет на алгоритм, так как Оболочка немедленно вызывает метод Add(T Value) базовой коллекции.)

  2. При десериализации в массив .Net создается временное значение List<T> для некоторого соответствующего T, и значения добавляются в том порядке, как в случае 1, либо через JsonSerializerInternalReader.PopulateList() или JsonSerializerInternalReader.PopulateMultidimensionalArray(). Впоследствии список преобразуется в массив после вызова либо Array.CreateInstance затем List<T>.ICollection.CopyTo(Array, Int32), либо CollectionUtils.ToMultidimensionalArray(). Оба создают массив, сохраняя порядок значений входящей коллекции.

  3. При десериализации неизменяемой коллекции коллекция должна иметь конструктор, который принимает IEnumerable<T>, где T - тип элемента коллекции. Это объясняется в примечаниях к выпуску для Json.NET 6.0.3 :

    Всем будущим создателям неизменяемых коллекций .NET: если ваша коллекция T имеет конструктор, который принимает IEnumerable<T>, то Json.NET автоматически сработает при десериализации в вашу коллекцию, иначе вам не повезет.

    Предполагая, что ваша неизменяемая коллекция имеет требуемый конструктор, алгоритм продолжает работу, как в случае 2, десериализацию до List<T>, а затем построение неизменной коллекции из списка со значениями в порядке, в котором они встречались и десериализовались.

Конечно, сама коллекция может перетасовать порядок значений:

Однако для базовых коллекций List<T> или T [] этого не произойдет.

...