Spring MVC - как вернуть простую строку как JSON в контроллере Rest
мой вопрос по существу является продолжением этой вопрос.
@RestController
public class TestController
{
@RequestMapping("/getString")
public String getString()
{
return "Hello World";
}
}
в приведенном выше Spring добавит "Hello World" в тело ответа. Как я могу вернуть строку в качестве ответа JSON? Я понимаю, что я мог бы добавить цитаты, но это больше похоже на хак.
пожалуйста, приведите примеры, которые помогут объяснить эту концепцию.
Примечание: я не хочу, чтобы это было написано прямо в тело ответа HTTP, я хочу верните строку в формате JSON (я использую свой контроллер с RestyGWT который требует, чтобы ответ был в действительном JSON формат.)
10 ответов
либо return text/plain
(например,возвращает только строковое сообщение от Spring MVC 3 Controller) или обернуть строку какой-то объект
public class StringResponse {
private String response;
public StringResponse(String s) {
this.response = s;
}
// get/set omitted...
}
Задайте тип ответа application/json
@RequestMapping(value = "/getString", method = RequestMethod.GET, produces = "application/json")
и у вас будет JSON, который выглядит как
{ "response" : "your string value" }
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 вы должны использовать класс-оболочку, как описано Шоном.
поскольку я опубликовал этот вопрос, я начал использовать JSONObject (maven информация о зависимости). Особенно работая с командой, я считаю, что легче ожидать, что строка будет возвращена, а не какой-то объект-оболочка, когда все, что я хочу, это простая строка.
Пример Использования:
@RestController
public class TestController
{
@RequestMapping("/getString")
public String getString()
{
return JSONObject.quote("Hello World");
}
}
вы можете легко вернуть JSON
С String
в собственность response
следующим образом
@RestController
public class TestController {
@RequestMapping((value = "/getString", produces = MediaType.APPLICATION_JSON_VALUE)
public Map getString() {
return Collections.singletonMap("response", "Hello World");
}
}
просто отмените регистрацию по умолчанию 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
доступен с весны 4.1.3, если вы работаете в предыдущей версии, вы можете реализовать ту же технику, используяconfigureMessageConverters
, это просто требует немного больше работы. - это был один из многих других возможных подходов, если ваш приложение только когда-либо возвращает JSON и никаких других типов контента, вам лучше пропустить конвертеры по умолчанию и добавить один конвертер Джексона. Другой подход-добавить преобразователи по умолчанию, но в другом порядке, чтобы конвертер Джексона был перед строковым. Это должно позволить методам действий контроллера диктовать, как они хотят, чтобы строка была преобразована в зависимости от типа носителя ответа.
добавить produces = "application/json"
на @RequestMapping
аннотация как:
@RequestMapping(value = "api/login", method = RequestMethod.GET, produces = "application/json")
Подсказка: в качестве возвращаемого значения, я рекомендую использовать ResponseEntity<List<T>>
тип. Потому что полученные данные в теле JSON должны быть массив или объект в соответствии с его спецификациями, а не один простой строка. Иногда это может вызвать проблемы (например, наблюдаемые в Angular2).
отличия:
вернулся String
как json: "example"
вернулся List<String>
как json:["example"]
Я знаю, что этот вопрос старый, но я тоже хочу внести свой вклад:
основное различие между другими ответами-это возврат hashmap.
@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"}
весной MVC 4 тип ответа по умолчанию для объектов-JSON. Поэтому все, что вам нужно сделать, это обернуть строку в какой-то предмет.
public class StringResponse {
private String response;
public StringResponse(String s) {
this.response = s;
}
// getters and setters
}
никаких изменений в контроллере, кроме возврата StringResponse
вместо строки.
добавьте эту аннотацию в свой метод
@RequestMapping(value = "/getString", method = RequestMethod.GET, produces = "application/json")