> Как лучше обработать ошибки парсинга JSON в Java (Java)
Уровень: senior · Роль: backend · Язык: Java · Категория: Технические вопросы
Компании: ИТ-Экспертиза
Стек: Java
> Пример ответа
Короткий ответ
На уровне senior нужно не просто ловить JsonProcessingException, а разделять синтаксические ошибки, несоответствие схеме и бизнес-валидацию. Используй Jackson с ObjectMapper, включай FAIL_ON_UNKNOWN_PROPERTIES по ситуации, оборачивай в доменную ошибку и возвращай клиенту 400 без утечки внутренних деталей. Логируй с контекстом, но без чувствительных данных.
Подробное объяснение
Парсинг JSON в Java почти всегда идёт через Jackson, Gson или JSON-B. Синтаксически некорректный JSON выбрасывает JsonParseException или JsonProcessingException - это ошибка клиента, а не сервера. Несоответствие структуры (например, строка вместо числа) даёт MismatchedInputException. Неизвестные поля контролируются DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES - на senior-уровне это осознанный trade-off между строгостью контракта и обратной совместимостью. Бизнес-правила (например, отрицательная сумма) проверяются отдельно через Bean Validation или ручную валидацию после десериализации. Ошибки нужно преобразовывать в доменные исключения, чтобы не протекали детали библиотеки. В Spring MVC HttpMessageNotReadableException уже обрабатывается, но кастомный @ExceptionHandler даёт контроль над телом ответа. Логирование должно включать correlation id, endpoint и фрагмент payload без PII. Для streaming-парсинга (JsonParser) ошибки возникают на этапе итерации, и их тоже нужно оборачивать.
На практике
В REST-контроллере создай @RestControllerAdvice, который ловит HttpMessageNotReadableException и возвращает ProblemDetail с кодом INVALID_JSON. Внутри сервиса, если парсишь вручную, используй ObjectMapper.readValue в try-catch и бросай InvalidPayloadException с причиной. Настрой ObjectMapper как bean: отключи FAIL_ON_UNKNOWN_PROPERTIES для публичных API, включи FAIL_ON_NULL_FOR_PRIMITIVES. Для Kafka-консьюмеров ошибки парсинга отправляй в DLQ, а не ретрай бесконечно. Не логируй весь payload на уровне ERROR - это риск утечки и раздувания логов. Используй StructuredArguments или MDC для контекста.
Пример кода
JAVApublic record OrderRequest(String id, BigDecimal amount) {}@RestControllerAdvicepublic class JsonErrorHandler {@ExceptionHandler(HttpMessageNotReadableException.class)public ResponseEntity<ProblemDetail> handleInvalidJson(HttpMessageNotReadableException ex) {Throwable cause = ex.getMostSpecificCause();String detail = cause instanceof JsonProcessingException? "Malformed JSON payload": "Invalid request body";ProblemDetail problem = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, detail);problem.setTitle("Invalid JSON");return ResponseEntity.badRequest().body(problem);}}@Servicepublic class OrderParser {private final ObjectMapper mapper;public OrderParser(ObjectMapper mapper) {this.mapper = mapper;}public OrderRequest parse(String raw) {try {OrderRequest request = mapper.readValue(raw, OrderRequest.class);validate(request);return request;} catch (JsonProcessingException e) {throw new InvalidPayloadException("Cannot parse order JSON", e);}}private void validate(OrderRequest request) {if (request.amount() == null || request.amount().signum() < 0) {throw new InvalidPayloadException("Amount must be non-negative");}}}
Как отвечать на собеседовании
Скажи, что на senior-уровне важно разделять типы ошибок: синтаксис, схема, бизнес-валидация. Упомяни Jackson и его feature-флаги. Покажи, что знаешь про HttpMessageNotReadableException в Spring и кастомный @ExceptionHandler. Расскажи про DLQ для асинхронных сценариев и про то, что нельзя светить stack trace клиенту. Добавь про логирование с контекстом и без PII. Если спросят про производительность, отметь streaming API и переиспользование ObjectMapper.
Что проверяет интервьюер
Понимание различий между типами ошибок парсинга. Знание Jackson и его конфигурации. Умение обрабатывать исключения в Spring без утечки деталей. Осознание trade-off между строгостью схемы и обратной совместимостью. Навык логирования и работы с DLQ. Способность предложить доменную модель ошибок вместо голых исключений библиотеки.
Типичные ошибки
Ловить общий Exception вместо конкретных типов. Возвращать клиенту stack trace или сообщение Jackson. Логировать весь payload с персональными данными. Игнорировать FAIL_ON_UNKNOWN_PROPERTIES и ломать контракт при добавлении поля. Смешивать синтаксическую и бизнес-валидацию в одном catch. Не обрабатывать ошибки в Kafka-консьюмере и зацикливать ретраи. Создавать новый ObjectMapper на каждый запрос.
> Похожие задачи по Java
Как избежать ошибки IndexOutOfBoundsException при итерации по JSON-массиву в Java
Приходилось ли работать с форматами XML и JSON для обмена данными?
> Похожие задачи по backend
Используете ли вы Kanban или Scrum
Какая алгоритмическая сложность доступа по ключу в map Go
Как избежать ошибки IndexOutOfBoundsException при итерации по JSON-массиву в Java
Приходилось ли работать с форматами XML и JSON для обмена данными?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью