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 85

10 ответов:

вернуть 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" in @RequestMapping аннотация как:

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

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

отличия:

вернулся String в формате JSON: "example"

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

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

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

основное различие между другими ответами-это возврат 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"}

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