簡體   English   中英

在 Spring Boot 中返回 JSON 對象作為響應

[英]Returning JSON object as response in Spring Boot

我在 Spring Boot 中有一個示例 RestController:

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

我正在使用 JSON 庫org.json

當我點擊 API /hello時,我得到一個異常說:

Servlet.service() 用於路徑 [] 上下文中的 servlet [dispatcherServlet] 引發異常 [請求處理失敗; 嵌套異常是 java.lang.IllegalArgumentException: No converter found for return value of type: class org.json.JSONObject] 根本原因

java.lang.IllegalArgumentException:沒有找到類型的返回值的轉換器:類 org.json.JSONObject

問題是什么? 有人可以解釋到底發生了什么嗎?

當您使用 Spring Boot web 時,Jackson 依賴是隱式的,我們不必明確定義。 如果使用 eclipse,您可以在依賴層次結構選項卡中的pom.xml中檢查 Jackson 依賴項。

並且由於您已使用@RestController進行注釋,因此無需進行顯式 json 轉換。 只需返回一個 POJO,jackson 序列化程序將負責轉換為 json。 與@Controller 一起使用時,相當於使用@ResponseBody 不是將@ResponseBody放置在每個控制器方法上,而是放置@RestController而不是vanilla @Controller ,默認情況下@ResponseBody應用於該控制器中的所有資源。
請參閱此鏈接: https : //docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-responsebody

您面臨的問題是因為返回的對象(JSONObject)沒有某些屬性的 getter。 您的意圖不是序列化這個 JSONObject,而是序列化一個 POJO。 所以只需返回POJO。
請參閱此鏈接: https : //stackoverflow.com/a/35822500/5039001

如果你想返回一個 json 序列化的字符串,那么只需返回該字符串。 在這種情況下,Spring 將使用 StringHttpMessageConverter 而不是 JSON 轉換器。

您當前的方法不起作用的原因是因為默認情況下使用 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" }

這有點受限制,因為添加子對象可能會變得更加困難。 Jackson 有自己的機制,使用ObjectNodeArrayNode 要使用它,您必須在服務/控制器中自動裝配ObjectMapper 然后你可以使用:

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

這種方法允許您添加子對象、數組並使用所有各種類型。

您可以按照@vagaasen 的建議將響應作為String返回,也可以使用 Spring 提供的ResponseEntity對象,如下所示。 通過這種方式,您還可以返回Http status code ,這在 webservice 調用中更有幫助。

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

您也可以為此使用哈希圖

@GetMapping
public HashMap<String, Object> get() {
    HashMap<String, Object> map = new HashMap<>();
    map.put("key1", "value1");
    map.put("results", somePOJO);
    return map;
}

更正確的為 API 查詢創建 DTO,例如 entityDTO:

  1. 實體列表的默認響應 OK:
 @GetMapping(produces=MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.OK) public List<EntityDto> getAll() { return entityService.getAllEntities(); }

但是如果你需要返回不同的 Map 參數,你可以使用接下來的兩個例子
2. 返回一個參數,如 map:

 @GetMapping(produces=MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Object> getOneParameterMap() { return ResponseEntity.status(HttpStatus.CREATED).body( Collections.singletonMap("key", "value")); }
  1. 如果您需要返回某些參數的映射(自 Java 9 起):
 @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Object> getSomeParameters() { return ResponseEntity.status(HttpStatus.OK).body(Map.of( "key-1", "value-1", "key-2", "value-2", "key-3", "value-3")); }
@RequestMapping("/api/status")
public Map doSomething()
{
    return Collections.singletonMap("status", myService.doSomething());
}

附注。 僅適用於 1 個值

使用ResponseEntity<ResponseBean>

在這里,您可以根據需要使用 ResponseBean 或 Any java bean 來返回 api 響應,這是最佳實踐。 我使用 Enum 進行響應。 它將返回 API 的狀態代碼和狀態消息。

@GetMapping(path = "/login")
public ResponseEntity<ServiceStatus> restApiExample(HttpServletRequest request,
            HttpServletResponse response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        loginService.login(username, password, request);
        return new ResponseEntity<ServiceStatus>(ServiceStatus.LOGIN_SUCCESS,
                HttpStatus.ACCEPTED);
    }

用於響應 ServiceStatus 或(ResponseBody)

    public enum ServiceStatus {

    LOGIN_SUCCESS(0, "Login success"),

    private final int id;
    private final String message;

    //Enum constructor
    ServiceStatus(int id, String message) {
        this.id = id;
        this.message = message;
    }

    public int getId() {
        return id;
    }

    public String getMessage() {
        return message;
    }
}

Spring REST API 應該具有以下鍵作為響應

  1. 狀態碼
  2. 留言

您將在下面得到最終答復

{

   "StatusCode" : "0",

   "Message":"Login success"

}

您可以根據您的要求使用 ResponseBody(java POJO、ENUM 等)。

如果您需要使用字符串返回 JSON 對象,則以下操作應該有效:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.ResponseEntity;
...

@RestController
@RequestMapping("/student")
public class StudentController {

    @GetMapping
    @RequestMapping("/")
    public ResponseEntity<JsonNode> get() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode json = mapper.readTree("{\"id\": \"132\", \"name\": \"Alice\"}");
        return ResponseEntity.ok(json);
    }
    ...
}

我使用 org.json.JSONObject 的 toMap() 方法在控制器中返回 Map<String,Object> ,如下所示。

@GetMapping("/json")
public Map<String, Object> getJsonOutput() {       
    JSONObject jsonObject = new JSONObject();
    //construct jsonObject here
    return jsonObject.toMap();
}

你可以這樣做 :

@RestController
@RequestMapping("/api")
class MyRestController
{
    @GetMapping(path = "/hello")
    public JSONObject sayHello()
    {
        return new JSONObject("{'aa':'bb'}").toMap();;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM