Spring MVC - Как вернуть простую строку в JSON в Rest Controller

Мой вопрос по существу является продолжением этого вопроса.

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

В приведенном выше примере Spring добавит "Hello World" в тело ответа. Как я могу вернуть строку как ответ JSON? Я понимаю, что могу добавить цитаты, но это больше похоже на хак.

Просьба привести примеры, которые помогут объяснить эту концепцию.

Примечание: Я не хочу, чтобы это было написано прямо в модуле ответа HTTP, я хочу вернуть String в формате JSON (я использую свой контроллер с RestyGWT, который требует, чтобы ответ находился в действительном JSON формат).

Ответ 1

Либо верните text/plain (как в Вернуть только строковое сообщение из контроллера Spring MVC 3), либо оберните вашу строку каким-то объектом

public class StringResponse {

    private String response;

    public StringResponse(String s) { 
       this.response = s;
    }

    // get/set omitted...
}


Установите тип ответа MediaType.APPLICATION_JSON_VALUE (= "application/json")

@RequestMapping(value = "/getString", method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)

и у вас будет JSON, который выглядит как

{  "response" : "your string value" }

Ответ 2

JSON по существу является строкой в ​​контексте PHP или JAVA. Это означает, что строка, действительная JSON, может быть возвращена в ответ. Следующее должно работать.

  @RequestMapping(value="/user/addUser", method=RequestMethod.POST)
  @ResponseBody
  public String addUser(@ModelAttribute("user") User user) {

    if (user != null) {
      logger.info("Inside addIssuer, adding: " + user.toString());
    } else {
      logger.info("Inside addIssuer...");
    }
    users.put(user.getUsername(), user);
    return "{\"success\":1}";
  }

Это нормально для простого ответа строки. Но для комплексного ответа JSON вы должны использовать класс оболочки, как описано Shaun.

Ответ 3

В одном проекте мы решили эту проблему с помощью JSONObject (информация о зависимостях maven). Мы выбрали это, потому что мы предпочитали возвращать простую строку, а не объект-оболочку. Вместо этого можно легко использовать внутренний вспомогательный класс, если вы не хотите добавлять новую зависимость.

Пример использования:

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

Ответ 4

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

@RestController
public class TestController {
    @RequestMapping(value = "/getString", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map getString() {
        return Collections.singletonMap("response", "Hello World");
    }
}

Ответ 5

Просто отмените регистрацию по умолчанию StringHttpMessageConverter:

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
  /**
   * Unregister the default {@link StringHttpMessageConverter} as we want Strings
   * to be handled by the JSON converter.
   *
   * @param converters List of already configured converters
   * @see WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
   */
  @Override
  protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.stream()
      .filter(c -> c instanceof StringHttpMessageConverter)
      .findFirst().ifPresent(converters::remove);
  }
}

Протестировано с помощью методов обработчика действий контроллера и обработчиков исключений контроллера:

@RequestMapping("/foo")
public String produceFoo() {
  return "foo";
}

@ExceptionHandler(FooApiException.class)
public String fooException(HttpServletRequest request, Throwable e) {
  return e.getMessage();
}

Заключительные примечания:

  • extendMessageConverters доступен с Spring 4.1.3, если они выполняются в предыдущей версии, вы можете реализовать ту же технику с помощью configureMessageConverters, это займет немного больше работы.
  • Это был один из подходов к многим другим возможным подходам, если ваше приложение только когда-либо возвращает JSON и другие типы содержимого, вам лучше пропускать преобразователи по умолчанию и добавить один конвертер Jackson. Другой подход заключается в добавлении преобразователей по умолчанию, но в другом порядке, так что преобразователь jackson находится перед строкой. Это должно позволить методам управления контроллером определять, как они хотят преобразовать String в зависимости от типа носителя ответа.

Ответ 6

Я знаю, что этот вопрос старый, но я бы тоже хотел внести свой вклад:

Основное различие между другими ответами - возвращение хэш-карты.

@GetMapping("...")
@ResponseBody
public HashMap<String, Object> endPointExample(...) {

    HashMap<String, Object> rtn = new LinkedHashMap<String, Object>();
    rtn.put("pic", image);
    rtn.put("potato", "King Potato");

    return rtn;

}

Это вернет:

{"pic":"a17fefab83517fb...beb8ac5a2ae8f0449","potato":"King Potato"}

Ответ 7

Добавьте produces = "application/json" в @RequestMapping аннотацию, например:

@RequestMapping(value = "api/login", method = RequestMethod.GET, produces = "application/json")

Подсказка: в качестве возвращаемого значения я рекомендую использовать тип ResponseEntity<List<T>>. Поскольку полученные данные в теле JSON должны быть массивом или объектом в соответствии со своими спецификациями, а не одной простой строкой . Иногда это может вызвать проблемы (например, Observables в Angular2).

Difference:

вернулся String как json: "example"

вернулся List<String> как json: ["example"]

Ответ 8

Добавить @ResponseBody аннотацию, которая будет записывать возвращаемые данные в выходной поток.

Ответ 9

Spring MVC 4 типом ответа по умолчанию для объектов является JSON. Так что все, что вам нужно сделать, это обернуть вашу строку в некоторый объект.

    public class StringResponse {

   private String response;

   public StringResponse(String s) { 
       this.response = s;
   }

    // getters and setters 
}

Никаких изменений в контроллере, кроме возврата StringResponse вместо String.

Ответ 10

Сделай просто:

    @GetMapping("/health")
    public ResponseEntity<String> healthCheck() {
        LOG.info("REST request health check");
        return new ResponseEntity<>("{\"status\" : \"UP\"}", HttpStatus.OK);
    }

Ответ 11

Добавьте эту аннотацию к вашему методу

@RequestMapping(value = "/getString", method = RequestMethod.GET, produces = "application/json")