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")