web-dev-qa-db-ja.com

Spring Bootで応答としてJSONオブジェクトを返す

Spring BootにRestControllerのサンプルがあります:

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

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


}

JSONライブラリorg.jsonを使用しています

API /helloをヒットすると、次のような例外が表示されます。

パス[]を持つコンテキストのサーブレット[dispatcherServlet]のServlet.service()が例外をスローしました[リクエスト処理に失敗しました。ネストされた例外はJava.lang.IllegalArgumentExceptionです:型の戻り値のコンバーターが見つかりません:クラスorg.json.JSONObject]根本原因

Java.lang.IllegalArgumentException:型の戻り値のコンバーターが見つかりません:クラスorg.json.JSONObject

問題は何ですか?誰かが正確に何が起こっているのか説明できますか?

48
iwekesi

Spring Boot Webを使用しているため、Jackson依存関係は暗黙的であり、明示的に定義する必要はありません。 Eclipseを使用している場合、依存関係階層タブのpom.xmlでJacksonの依存関係を確認できます。

また、@RestControllerアノテーションを付けたので、明示的なJSON変換を行う必要はありません。 POJOを返すだけで、jacksonシリアライザーがjsonへの変換を処理します。 @Controllerで使用する場合、@ResponseBodyを使用するのと同等です。すべてのコントローラーメソッドに@ResponseBodyを配置するのではなく、Vanilla @RestControllerおよび@Controllerの代わりに@ResponseBodyをそのコントローラーのすべてのリソースに適用します。
このリンクを参照してください:https://docs.spring.io/spring/docs/current/spring-framework -reference/html/mvc.html#mvc-ann-responsebody

あなたが直面している問題は、返されたオブジェクト(JSONObject)が特定のプロパティのゲッターを持っていないためです。また、このJSONObjectをシリアル化するのではなく、POJOをシリアル化するのが目的です。したがって、POJOを返すだけです。
このリンクを参照してください:https://stackoverflow.com/a/35822500/5039001

JSONシリアル化された文字列を返したい場合は、文字列を返します。この場合、SpringはJSONコンバーターの代わりにStringHttpMessageConverterを使用します。

59
prem kumar

現在のアプローチが機能しない理由は、オブジェクトのシリアル化と非シリアル化にデフォルトでJacksonが使用されているためです。ただし、JSONObjectをシリアル化する方法はわかりません。動的なJSON構造を作成する場合は、Mapを使用できます。例:

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

これにより、次のJSON応答が発生します。

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

子オブジェクトの追加が少し難しくなる可能性があるため、これは少し制限されています。ジャクソンには、ObjectNodeArrayNodeを使用する独自のメカニズムがあります。それを使用するには、サービス/コントローラーでObjectMapperを自動配線する必要があります。次に使用できます:

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

このアプローチにより、子オブジェクト、配列を追加し、すべてのさまざまなタイプを使用できます。

33
g00glen00b

@vagaasenが示唆するようにStringとして応答を返すか、以下のようにSpringが提供するResponseEntityオブジェクトを使用できます。この方法により、Http status codeを返すこともできます。これは、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

このためにハッシュマップを使用することもできます

@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。 1つの値に対してのみ機能します

3
Dmitry