Spring MVC - How to return simple String as JSON i

2019-01-07 05:09发布

问题:

My question is essentially a follow-up to this question.

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

In the above, Spring would add "Hello World" into the response body. How can I return a String as a JSON response? I understand that I could add quotes, but that feels more like a hack.

Please provide any examples to help explain this concept.

Note: I don't want this written straight to the HTTP Response body, I want to return the String in JSON format (I'm using my Controller with RestyGWT which requires the response to be in valid JSON format).

回答1:

Either return text/plain (as in Return only string message from Spring MVC 3 Controller) OR wrap your String is some object

public class StringResponse {

    private String response;

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

    // get/set omitted...
}


Set your response type to application/json

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

and you'll have a JSON that looks like

{  "response" : "your string value" }


回答2:

JSON is essentially a String in PHP or JAVA context. That means string which is valid JSON can be returned in response. Following should work.

  @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}";
  }

This is okay for simple string response. But for complex JSON response you should use wrapper class as described by Shaun.



回答3:

Since I posted this question, I have started using JSONObject (maven dependency info). Especially working with a team, I find it easier to expect a String to be returned rather than some wrapper object when all I want is a simple String.

Example Usage:

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


回答4:

You can easily return JSON with String in property response as following

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


回答5:

Simply unregister the default StringHttpMessageConverter instance:

@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);
  }
}

Tested with both controller action handler methods and controller exception handlers:

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

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

Final notes:

  • extendMessageConverters is available since Spring 4.1.3, if are running on a previous version you can implement the same technique using configureMessageConverters, it just takes a little bit more work.
  • This was one approach of many other possible approaches, if your application only ever returns JSON and no other content types, you are better off skipping the default converters and adding a single jackson converter. Another approach is to add the default converters but in different order so that the jackson converter is prior to the string one. This should allow controller action methods to dictate how they want String to be converted depending on the media type of the response.


回答6:

I know that this question is old but i would like to contribute too:

The main difference between others responses is the hashmap return.

@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;

}

This will return:

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


回答7:

Add produces = "application/json" in @RequestMapping annotation like:

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

Hint: As a return value, i recommend to use ResponseEntity<List<T>> type. Because the produced data in JSON body need to be an array or an object according to its specifications, rather than a single simple string. It may causes problems sometimes (e.g. Observables in Angular2).

Difference:

returned String as json: "example"

returned List<String> as json: ["example"]



回答8:

Add @ResponseBody annotation, which will write return data in output stream.



回答9:

In spring MVC 4 the default response type for objects is JSON. So all you need to do is wrap your String in some Object.

    public class StringResponse {

   private String response;

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

    // getters and setters 
}

No modifications to the controller, except returning the StringResponse instead of the String.



回答10:

Add this annotation to your method

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