Как обрабатывать JSON объекты из файла с одинаковыми элементами
Что проверяют
Умеете ли вы превратить массив однотипных объектов из файла в типизированную коллекцию и работать с ней: группировать, убирать дубли, считать. Формулировка размытая, поэтому хороший ход сначала уточнить, что значит «одинаковые»: объекты одной структуры, полные дубли или повтор по ключу. Следом часто спрашивают, что делать с файлом на несколько гигабайт.
Как отвечать
Каркас на современном .NET, где стандартом стал встроенный System.Text.Json:
- модель:
record Item(string Sku, string Name, int Quantity), массив однотипных объектов ложится вList<Item>одним вызовомJsonSerializer.Deserialize<List<Item>>(json, options); - регистр имён:
System.Text.Jsonпо умолчанию чувствителен к регистру, в отличие от Newtonsoft.Json. Для JSON в camelCase нуженPropertyNameCaseInsensitive = trueилиnew JsonSerializerOptions(JsonSerializerDefaults.Web); - чтение файла: маленький файл читают через
File.ReadAllText, но лучше открыть потокFile.OpenReadи вызватьDeserializeAsync; - большой файл:
JsonSerializer.DeserializeAsyncEnumerable<Item>(stream)отдаёт элементы массива по одному черезawait foreach, не держа весь список в памяти; - дубли: полные дубли убирает
Distinct(), у record равенство по значению уже есть; дубли по ключуDistinctBy(x => x.Sku); сумму по одинаковым позициям даётGroupBy(x => x.Sku)сSum, быстрый поискToDictionaryилиToLookup, если ключ повторяется; - ошибки: битый файл бросает
JsonExceptionс номером строки и позицией, его ловят отдельно отIOException.
Где спотыкаются
Делают ToDictionary по полю, которое повторяется, и получают ArgumentException на первом же дубле. Для неуникального ключа нужен ToLookup или GroupBy.
Переносят привычки Newtonsoft на System.Text.Json и удивляются, что свойства остались пустыми: в файле camelCase, а сравнение имён по умолчанию строгое.
Забывают, что повтор ключа внутри одного объекта сериализатор по умолчанию не отвергает: в свойство молча попадает последнее значение. Если это важно, проверяйте файл до десериализации.