Почему Джексон не принимает пустые списки как нулевые значения? - PullRequest
1 голос
/ 09 апреля 2020

В моей компании есть веб-служба Java, использующая Spring Web, которая принимает JSON через REST API. Мы используем Maven и наша версия Джексона 2.9. Мы пытаемся предотвратить появление исключений десериализации, когда интегратор передает пустой список, когда наш API его не ожидает.

Например, вот мой класс приложения:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@EnableWebMvc
@SpringBootApplication
public class ExampleApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

Student. java class:

import lombok.Data;
import java.util.Map;

@Data
public class Student {

    private String firstName;
    private String lastName;
    private Map<String, String> classGrades;
}

A StudentController:

package com.example.example.controllers;

import com.example.example.models.Student;
import org.springframework.http.RequestEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.stream.Stream;

@RestController()
@RequestMapping(value = "/Students/", produces = "application/json")
public class StudentController {

    @PostMapping(path = "")
    public RequestEntity<Student> createNewStudent(@RequestBody Student student) {

       return null;
    }
}

Приложение.properties:

spring.jackson.deserialization.accept-empty-array-as-null-object=true

Пом. xml содержит все зависимости по умолчанию, с добавлением следующего:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>

Каждый другой файл проекта по умолчанию соответствует структуре проекта, созданной инициализатором Spring. Ожидаемое тело запроса (JSON сформировано с использованием Postman):

{
  "firstName": "Mark",
  "lastName": "Twain",
  "classGrades": {

  }
}

Работает просто отлично. Однако, если какое-либо поле (хотя в нашем конкретном c случае, поле classGrades) получает пустой список, генерируется исключение десериализации Джексона. Пример JSON неудавшегося запроса:

{
  "firstName": "Mark",
  "lastName": "Twain",
  "classGrades": []
}

И выброшенное исключение:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 65, column: 28] 

Согласно странице проекта github , опция ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT должен решить эту проблему для нас. Мы попытались установить это непосредственно для объекта конфигурации ObjectMapper и в пределах application.properties, используя строку:

spring.jackson.deserialization.accept-empty-array-as-null-object=true

Ни один из методов, похоже, не сработал. В настоящее время мы используем обходной путь, используя аннотацию @JsonDeserialize(using = MyCustomDeserializer.class) для полей, склонных к этой проблеме. Однако мы хотели бы, чтобы все наши поля по умолчанию рассматривали пустые списки как нулевые.

Неужели мы неправильно понимаем параметр конфигурации и используем его неправильно? Есть ли способ обрабатывать пустые списки как нулевые в нашем приложении, и если да, то как мы можем выполнить sh this?

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

В этом примере моей проблемой была аннотация @EnableWebMvc в классе ExampleApplication. Удаление этой аннотации позволило мне успешно отправить пустой массив моей конечной точке, которая затем получила его как нулевой объект.

Примечание

Моя первоначальная проблема все еще существует в моей заявление компании, даже после удаления аннотации. Однако, похоже, что это может быть проблема с другим параметром, который может конфликтовать с ...accept-empty-arrays-as-null-object.

0 голосов
/ 09 апреля 2020

Карта сериализуется как

{ "k1": "v1", "k2": "v2"}

Пустая карта сериализуется как

{ }

В вашем примере вы пытаетесь вставить [], который представляет пустой список или массив в карту, и именно поэтому Джексон жалуется. Просто нельзя сопоставить пустой список с картой. Это также объясняет, почему включение ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT не имеет никакого эффекта

Обновление

Я был не прав. Джексон может отобразить пустой массив на карту. Создан минимальный пример Springboot, который использует свойство spring.jackson.deserialization.accept-empty-array-as-null-object = true и может сопоставить пустой массив [] с Map

Отметьте здесь , если хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...