web-dev-qa-db-fra.com

Renvoi d'un objet JSON en réponse au démarrage initial

J'ai un exemple de RestController dans Spring Boot:

@RestController
@RequestMapping("/api")
class MyRestController
{

    @GetMapping(path = "/hello")
    public JSONObject sayHello()
    {
        return new JSONObject("{'aa':'bb'}");
    }


}

J'utilise la bibliothèque JSON org.json

Lorsque je frappe sur API /hello, je reçois une exception disant:

Servlet.service () pour servlet [dispatcherServlet] dans le contexte du chemin [] renvoyé une exception [Le traitement de la demande a échoué; L'exception imbriquée est Java.lang.IllegalArgumentException: aucun convertisseur trouvé pour une valeur de retour de type: classe org.json.JSONObject] avec une cause principale.

Java.lang.IllegalArgumentException: aucun convertisseur trouvé pour une valeur de retour de type: class org.json.JSONObject

Quelle est la solution? Quelqu'un peut-il expliquer ce qui se passe exactement?

48
iwekesi

Comme vous utilisez le site Web Spring Boot, la dépendance de Jackson est implicite et il n’est pas nécessaire de définir explicitement. Vous pouvez vérifier la dépendance de Jackson dans votre pom.xml de l'onglet hiérarchie des dépendances si vous utilisez Eclipse.

Et comme vous l'avez annoté avec @RestController, il n'est pas nécessaire d'effectuer une conversion JSON explicite. Il suffit de retourner un POJO et le sérialiseur jackson se chargera de la conversion en json. Cela équivaut à utiliser @ResponseBody lorsqu'il est utilisé avec @Controller. Plutôt que de placer @ResponseBody sur chaque méthode de contrôleur, nous plaçons @RestController à la place de Vanilla @Controller et @ResponseBody par défaut est appliqué à toutes les ressources de ce contrôleur.
Référer ce lien: https://docs.spring.io/spring/docs/current/spring-framework -reference/html/mvc.html # mvc-ann-responsebody

Le problème que vous rencontrez est dû au fait que l'objet renvoyé (JSONObject) n'a pas de getter pour certaines propriétés. Et votre intention n'est pas de sérialiser ce JSONObject mais plutôt de sérialiser un POJO. Donc, retournez le POJO.
Consultez ce lien: https://stackoverflow.com/a/35822500/5039001

Si vous voulez renvoyer une chaîne sérialisée JSON, renvoyez-la simplement. Dans ce cas, Spring utilisera StringHttpMessageConverter au lieu du convertisseur JSON.

59
prem kumar

Votre approche actuelle ne fonctionne pas parce que Jackson est utilisé par défaut pour sérialiser et désérialiser des objets. Cependant, il ne sait pas comment sérialiser le JSONObject. Si vous souhaitez créer une structure JSON dynamique, vous pouvez utiliser un Map, par exemple:

@GetMapping
public Map<String, String> sayHello() {
    HashMap<String, String> map = new HashMap<>();
    map.put("key", "value");
    map.put("foo", "bar");
    map.put("aa", "bb");
    return map;
}

Cela conduira à la réponse JSON suivante:

{ "key": "value", "foo": "bar", "aa": "bb" }

C'est un peu limité, car il peut devenir un peu plus difficile d'ajouter des objets enfants. Jackson a cependant son propre mécanisme, utilisant ObjectNode et ArrayNode. Pour l'utiliser, vous devez connecter automatiquement ObjectMapper à votre service/contrôleur. Ensuite, vous pouvez utiliser:

@GetMapping
public ObjectNode sayHello() {
    ObjectNode objectNode = mapper.createObjectNode();
    objectNode.put("key", "value");
    objectNode.put("foo", "bar");
    objectNode.put("number", 42);
    return objectNode;
}

Cette approche vous permet d'ajouter des objets enfants, des tableaux et d'utiliser tous les types.

33
g00glen00b

Vous pouvez soit renvoyer une réponse sous la forme String comme suggéré par @vagaasen, soit utiliser ResponseEntity Object fourni par Spring comme ci-dessous. De cette manière, vous pouvez également renvoyer Http status code, ce qui est plus utile pour les appels de service Web.

@RestController
@RequestMapping("/api")
public class MyRestController
{

    @GetMapping(path = "/hello", produces=MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Object> sayHello()
    {
         //Get data from service layer into entityList.

        List<JSONObject> entities = new ArrayList<JSONObject>();
        for (Entity n : entityList) {
            JSONObject entity = new JSONObject();
            entity.put("aa", "bb");
            entities.add(entity);
        }
        return new ResponseEntity<Object>(entities, HttpStatus.OK);
    }
}
30
Sangam Belose

vous pouvez aussi utiliser un hashmap pour cela

@GetMapping
public HashMap<String, Object> get() {
    HashMap<String, Object> map = new HashMap<>();
    map.put("key1", "value1");
    map.put("results", somePOJO);
    return map;
}
8
maximus
@RequestMapping("/api/status")
public Map doSomething()
{
    return Collections.singletonMap("status", myService.doSomething());
}

PS Ne fonctionne que pour 1 valeur

3
Dmitry