Spring MVC - comment rendre une chaîne simple comme JSON dans le contrôleur Rest
ma question est essentiellement une suite à cette question .
@RestController
public class TestController
{
@RequestMapping("/getString")
public String getString()
{
return "Hello World";
}
}
dans ce qui précède, Spring ajouterait "Hello World" dans le corps de réponse. Comment retourner une chaîne comme réponse JSON? Je comprends que je puisse ajouter des citations, mais ça ressemble plus à un piratage.
veuillez fournir des exemples pour expliquer ce concept.
Note: je n'ai pas je veux que cela soit écrit directement au corps de réponse HTTP, je veux retourner la chaîne au format JSON (j'utilise mon contrôleur avec RestyGWT qui exige que la réponse soit dans JSON valide format.)
10 réponses
soit retourner text/plain
(comme dans Return only string message from Spring MVC 3 Controller ) soit envelopper votre chaîne de caractères est un objet quelconque
public class StringResponse {
private String response;
public StringResponse(String s) {
this.response = s;
}
// get/set omitted...
}
Définissez votre type de réponse à application/json
@RequestMapping(value = "/getString", method = RequestMethod.GET, produces = "application/json")
et vous aurez un JSON qui ressemble à
{ "response" : "your string value" }
JSON est essentiellement une chaîne de caractères en PHP ou en JAVA. Cela signifie que la chaîne de caractères qui est valide JSON peut être retournée en réponse. Suivant devrait fonctionner.
@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}";
}
ceci est correct pour la réponse de chaîne simple. Mais pour une réponse JSON complexe, vous devez utiliser la classe wrapper telle que décrite par Shaun.
depuis que j'ai posté cette question, j'ai commencé à utiliser JSONObject (maven info dépendance ). En travaillant surtout avec une équipe, je trouve qu'il est plus facile de s'attendre à ce qu'une chaîne de caractères soit retournée plutôt qu'un objet enveloppant quand tout ce que je veux c'est une simple chaîne de caractères.
Exemple D'Usage:
@RestController
public class TestController
{
@RequestMapping("/getString")
public String getString()
{
return JSONObject.quote("Hello World");
}
}
vous pouvez facilement retourner JSON
avec String
dans la propriété response
comme suit
@RestController
public class TestController {
@RequestMapping((value = "/getString", produces = MediaType.APPLICATION_JSON_VALUE)
public Map getString() {
return Collections.singletonMap("response", "Hello World");
}
}
désinscrire simplement la valeur par défaut 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);
}
}
testé à la fois avec les méthodes de gestion de l'action du contrôleur et avec les méthodes de gestion des exceptions du contrôleur:
@RequestMapping("/foo")
public String produceFoo() {
return "foo";
}
@ExceptionHandler(FooApiException.class)
public String fooException(HttpServletRequest request, Throwable e) {
return e.getMessage();
}
Final notes:
-
extendMessageConverters
est disponible depuis le printemps 4.1.3, si sont en cours d'exécution sur une version précédente , vous pouvez mettre en œuvre la même technique en utilisantconfigureMessageConverters
, il suffit d'un peu plus de travail. - C'était une approche parmi beaucoup d'autres approches possibles, si votre application ne renvoie que JSON et aucun autre type de contenu, Vous feriez mieux de sauter les convertisseurs par défaut et d'ajouter un seul convertisseur jackson. Une autre approche consiste à ajouter les convertisseurs par défaut mais dans un ordre différent afin que le convertisseur jackson soit antérieur à celui de la chaîne. Cela devrait permettre aux méthodes d'action du controller de dicter comment ils veulent que la chaîne soit convertie en fonction du type de média de la réponse.
ajouter produces = "application/json"
dans @RequestMapping
annotation comme:
@RequestMapping(value = "api/login", method = RequestMethod.GET, produces = "application/json")
indice: comme valeur de retour, je recommande d'utiliser le type ResponseEntity<List<T>>
. Parce que les données produites dans le corps de JSON doivent être un tableau ou un objet selon ses spécifications, plutôt qu'une simple chaîne . Il peut parfois causer des problèmes (par exemple Observables en Angular2).
Différence:
retourné String
json: "example"
retourné List<String>
json: ["example"]
ajouter @ResponseBody
annotation, qui écrira les données de retour dans le flux de sortie.
je sais que cette question Est ancienne mais je voudrais y contribuer aussi:
la principale différence entre les autres réponses est le retour 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;
}
Ce sera de retour:
{"pic":"a17fefab83517fb...beb8ac5a2ae8f0449","potato":"King Potato"}
au printemps MVC 4 le type de réponse par défaut pour les objets est JSON. Tout ce que vous avez à faire, c'est envelopper votre ficelle dans un objet.
public class StringResponse {
private String response;
public StringResponse(String s) {
this.response = s;
}
// getters and setters
}
aucune modification au contrôleur, sauf retourner le StringResponse
à la place de la chaîne.
ajouter cette annotation à votre méthode
@RequestMapping(value = "/getString", method = RequestMethod.GET, produces = "application/json")