> Как обрабатывать JSON объекты из файла с одинаковыми элементами (C# /.NET)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Ozon

Стек: C# /.NET

> Пример ответа

При работе с JSON, содержащим дублирующиеся ключи, стандартные десериализаторы (например, System.Text.Json или Newtonsoft.Json) по умолчанию выбрасывают исключение или берут последнее значение. Чтобы корректно обработать такие данные, нужно использовать кастомные стратегии.1. Использование JsonDocument (System.Text.Json):
Позволяет вручную обойти все элементы и собрать дубликаты в коллекцию.

CSHARP
using System.Text.Json;
string json = File.ReadAllText("data.json");
using JsonDocument doc = JsonDocument.Parse(json);
JsonElement root = doc.RootElement;
var duplicates = new Dictionary<string, List<JsonElement>>();
foreach (var property in root.EnumerateObject())
{
if (!duplicates.ContainsKey(property.Name))
duplicates[property.Name] = new List<JsonElement>();
duplicates[property.Name].Add(property.Value);
}

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

CSHARP
public class DuplicateKeyConverter<T> : JsonConverter<Dictionary<string, List<T>>>
{
public override Dictionary<string, List<T>> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var result = new Dictionary<string, List<T>>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string key = reader.GetString();
reader.Read();
var value = JsonSerializer.Deserialize<T>(ref reader, options);
if (!result.ContainsKey(key))
result[key] = new List<T>();
result[key].Add(value);
}
else if (reader.TokenType == JsonTokenType.EndObject)
break;
}
return result;
}
// Write - не требуется для чтения
}

3. Обработка на уровне JObject (Newtonsoft.Json):
Используйте JsonLoadSettings с флагом DuplicatePropertyNameHandling.

CSHARP
var settings = new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace };
JObject obj = JObject.Parse(File.ReadAllText("data.json"), settings);
// Теперь дубликаты заменяются последним значением, но можно и игнорировать

Рекомендация: Если дубликаты - это ошибка данных, лучше валидировать JSON перед обработкой. Если же это допустимая структура (например, логи), используйте JsonDocument для потокового чтения без загрузки всего файла в память.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью