Простая строка как возвращаемое значение JSON в контроллере останова spring

Посмотрим на следующий простой тестовый контроллер (используется с Spring 4.0.3):

@RestController
public class TestController
{
    @RequestMapping("/getList")
    public List<String> getList()
    {
        final List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        return list;
    }

    @RequestMapping("/getString")
    public String getString()
    {
        return "Hello World";
    }
}

В теории оба метода контроллера должны возвращать действительный JSON. Вызов первого метода контроллера действительно возвращает следующий массив JSON:

$ curl -i -H "Accept: application/json" http://localhost:8080/getList
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

["1","2"]

Но второй метод контроллера возвращает строку без кавычек, которая не является допустимой строкой JSON:

$ curl -i -H "Accept: application/json" http://localhost:8080/getString
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

Hello World

Почему это так? Может ли он быть настроен? Это ошибка? Или особенность, которую я не понимаю?

Ответ 1

Когда вы возвращаете объект String, Spring MVC интерпретирует это как содержимое, чтобы помещать тело ответа и не модифицирует его дальше. Если вы хотите, чтобы фактическая строка была ответом JSON, вам нужно либо процитировать ее самостоятельно, либо явно запустить через Джексона.

Ответ 2

Вы можете удалить StringHttpMessageConverter, который был зарегистрирован перед преобразователем jackson, - как указано в комментарии.

/**
 * Unregister the default {@link StringHttpMessageConverter} as we want
 * Strings to be handled by the JSON converter.
 *
 * Our MappingJackson2HttpMessageConverter will deal with strings.
 *
 * @param converters
 *            List of already configured converters
 */
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

    Iterator<HttpMessageConverter<?>> iterator = converters.iterator();

    while (iterator.hasNext()) {
        HttpMessageConverter<?> converter = iterator.next();

        if (converter instanceof StringHttpMessageConverter) {
            iterator.remove();
        }
    }
}

Ответ 3

Если вы хотите вернуть объект String, Spring MVC интерпретирует это как содержимое, которое нужно поместить в тело ответа и не будет изменять его дальше. Если вы хотите, чтобы фактическая строка была ответом JSON, вам нужно либо процитировать ее самостоятельно, либо явно запустить через Джексона.

@RestController
public class TestController
{
   @RequestMapping("/getString")
   public String getString()
  {
    return JSONObject.quote("Hello World");
  }
}

Ответ 4

Вот шаги, которые я сделал для этого:

  • Добавить зависимость в файле pom:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.3</version>
    </dependency>
    
  • Поместите @ResponseBody аннотацию на свой метод следующим образом:

    @RequestMapping(value = "/getCountries", method = RequestMethod.GET)    
    @ResponseBody    
    public List<Country> getCountries() {    
        return countryDAO.list();    
    }