> Как обрабатывать отсутствие одинаковых строк в JSON (C#)
Уровень: senior · Роль: backend · Язык: C# · Категория: Технические вопросы
Компании: Ozon
Стек: C# /.NET
> Пример ответа
Короткий ответ
В C# для JSON отсутствие одинаковых строк обычно означает, что нужно обработать ситуацию, когда в массиве или объекте нет дубликатов. Это не ошибка парсинга, а бизнес-случай. Следует явно проверять наличие повторов через группировку или Distinct, а при необходимости возвращать пустой результат, null или бросать исключение. Ключевой момент - не полагаться на неявное поведение System.Text.Json или Newtonsoft.Json, а задавать политику на уровне домена.
Подробное объяснение
Под "отсутствием одинаковых строк" в JSON можно понимать две разные задачи. Первая - в JSON-массиве строк нет двух одинаковых значений, и нужно корректно обработать этот факт. Вторая - при десериализации в словарь или объект с ключами-строками отсутствует ожидаемый дубликат, хотя по логике он должен быть. На уровне senior-разработчика важно разделять эти сценарии и не смешивать валидацию данных с обработкой исключений.
Если речь о массиве строк, то после десериализации в List<string> или string[] можно проверить уникальность через GroupBy или Distinct. При отсутствии дубликатов поведение зависит от контракта: либо это нормально и возвращается исходная коллекция, либо это нарушение инварианта и нужно выбросить InvalidOperationException или вернуть Result-подобный объект. В .NET принято избегать исключений для ожидаемых бизнес-ситуаций, поэтому лучше использовать явные проверки и Try-паттерны.
Если речь о JSON-объекте, где ключи должны быть уникальными, то стандарт JSON не запрещает дубликаты, но большинство парсеров берут последнее значение. В System.Text.Json при десериализации в Dictionary<string, T> дубликаты ключей приводят к исключению JsonException только если включена опция AllowDuplicateProperties = false (по умолчанию в .NET 8+ дубликаты перезаписываются). Для Newtonsoft.Json поведение аналогично: последний ключ побеждает. Поэтому "отсутствие одинаковых строк" может означать, что дубликатов просто нет, и это не требует специальной обработки, кроме проверки ожидаемого количества.
На уровне архитектуры важно определить, является ли уникальность строки частью контракта. Если да, то проверка должна быть явной и документированной. Если нет, то не нужно добавлять лишние проверки, которые усложняют код и снижают производительность. Также стоит учитывать регистрозависимость: в C# string по умолчанию сравнивается с учётом регистра, но для JSON-ключей часто используют StringComparer.OrdinalIgnoreCase. Это влияет на то, считаются ли строки одинаковыми.
На практике
На практике в backend-сервисе на C# чаще всего приходит JSON-массив строк, и нужно понять, есть ли в нём дубликаты. Для этого после десериализации применяют Distinct() или GroupBy(). Если дубликатов нет, а по бизнес-логике они ожидались, возвращают 400 Bad Request с понятным сообщением. Если дубликаты не ожидались, но появились, это может быть признаком ошибки на стороне клиента или атаки, поэтому логируют и отклоняют запрос.
Для JSON-объектов с ключами-строками важно явно указать политику дубликатов при настройке сериализатора. В System.Text.Json можно использовать JsonSerializerOptions с AllowDuplicateProperties (в .NET 8+) или вручную проверять через JsonDocument. В Newtonsoft.Json есть DuplicatePropertyHandling. Это позволяет избежать неявного перезаписывания и сделать поведение предсказуемым.
Также стоит помнить о производительности: GroupBy и Distinct создают дополнительные аллокации. Для больших массивов лучше использовать HashSet<string> с нужным компаратором. Это особенно важно в highload-сценариях, где каждый лишний проход по коллекции может быть заметен.
Пример кода
CSHARPusing System;using System.Collections.Generic;using System.Linq;using System.Text.Json;public class JsonStringUniqueness{public static bool HasDuplicates(string jsonArray){var strings = JsonSerializer.Deserialize<List<string>>(jsonArray);if (strings == null) return false;var set = new HashSet<string>(StringComparer.Ordinal);foreach (var s in strings){if (!set.Add(s))return true;}return false;}public static List<string> GetUniqueOrThrow(string jsonArray){var strings = JsonSerializer.Deserialize<List<string>>(jsonArray);if (strings == null)throw new ArgumentException("JSON array is null");var set = new HashSet<string>(StringComparer.Ordinal);var result = new List<string>();foreach (var s in strings){if (set.Add(s))result.Add(s);}if (result.Count != strings.Count)throw new InvalidOperationException("Duplicate strings are not allowed");return result;}}
Как отвечать на собеседовании
Начните с уточнения, что именно имеется в виду: отсутствие дубликатов в массиве строк или отсутствие ожидаемого дубликата ключа в JSON-объекте. Затем объясните, что в C# для массивов строк используется HashSet или Distinct с явным компаратором. Для JSON-объектов важно указать, что стандарт JSON не запрещает дубликаты ключей, но парсеры ведут себя по-разному, и это нужно контролировать через настройки. Подчеркните, что обработка отсутствия дубликатов - это бизнес-решение, а не техническая ошибка, поэтому лучше возвращать результат или использовать Try-паттерн, а не бросать исключения без необходимости. Упомяните про регистрозависимость и производительность.
Что проверяет интервьюер
Интервьюер хочет увидеть, что кандидат различает уровни: парсинг JSON, валидация данных и бизнес-логика. Проверяется понимание поведения System.Text.Json и Newtonsoft.Json при дубликатах ключей, умение работать с HashSet и компараторами, а также навык выбирать между исключениями и возвратом результата. Также важно, чтобы кандидат учитывал регистрозависимость и производительность на больших данных. Ожидается, что senior не будет путать отсутствие дубликатов с ошибкой десериализации и сможет предложить чистое, поддерживаемое решение.
Типичные ошибки
Частая ошибка - использовать Distinct() без указания компаратора, что приводит к регистрозависимому сравнению, тогда как JSON-ключи часто должны сравниваться без учёта регистра. Другая ошибка - полагаться на то, что парсер сам выбросит исключение при дубликатах ключей, хотя по умолчанию многие парсеры просто перезаписывают значение. Также часто путают отсутствие дубликатов с отсутствием данных и возвращают null вместо пустой коллекции. Ещё одна ошибка - бросать исключение для ожидаемой бизнес-ситуации, что усложняет обработку и снижает производительность. Наконец, забывают про многопоточность и конкурентный доступ к HashSet, если проверка выполняется в параллельном коде.
> Похожие задачи по C#
Как реализовать чтение JSON по строкам с использованием потоков
Как пропускать некорректный JSON и продолжать обработку
Как реализовать обработку больших JSON файлов, которые не помещаются в память
> Похожие задачи по backend
Можно ли из класса контроллера в Java вернуть объект, который сериализуется в JSON
Как реализовать чтение JSON по строкам с использованием потоков
Как пропускать некорректный JSON и продолжать обработку
Как реализовать обработку больших JSON файлов, которые не помещаются в память
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью