Ich habe ein Beispiel RestController in Spring Boot:
@RestController
@RequestMapping("/api")
class MyRestController
{
@GetMapping(path = "/hello")
public JSONObject sayHello()
{
return new JSONObject("{'aa':'bb'}");
}
}
Ich verwende die JSON-Bibliothek org.json
Wenn ich auf API drücke /hello
, wird eine Ausnahme angezeigt:
Servlet.service () für Servlet [dispatcherServlet] im Kontext mit Pfad [] hat eine Ausnahme ausgelöst [Anforderungsverarbeitung fehlgeschlagen; verschachtelte Ausnahme ist java.lang.IllegalArgumentException: Kein Konverter für Rückgabewert vom Typ: Klasse org.json.JSONObject] mit Grundursache gefunden
java.lang.IllegalArgumentException: Für den Rückgabewert vom Typ: class org.json.JSONObject wurde kein Konverter gefunden
Was ist das Problem? Kann jemand erklären, was genau passiert?
java
json
spring-boot
response
iwekesi
quelle
quelle
@GetMapping(path = "/hello") @ResponseBody public String sayHello() {return"{'aa':'bb'}";}
Antworten:
Da Sie das Spring Boot-Web verwenden, ist die Jackson-Abhängigkeit implizit und muss nicht explizit definiert werden. Sie können in Ihrer
pom.xml
Registerkarte "Abhängigkeitshierarchie" nach Jackson-Abhängigkeit suchen, wenn Sie Eclipse verwenden.Und wie Sie mit kommentiert haben,
@RestController
müssen Sie keine explizite JSON-Konvertierung durchführen. Geben Sie einfach ein POJO zurück und der Jackson Serializer kümmert sich um die Konvertierung in JSON.@ResponseBody
Dies entspricht der Verwendung mit @Controller. Anstatt Platzierung@ResponseBody
auf jedem Controller - Methode setzen wir@RestController
anstelle von Vanille@Controller
und@ResponseBody
ist standardmäßig auf alle Ressourcen in diesem Controller angewendet.Verweisen Sie auf diesen Link: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
Das Problem besteht darin, dass das zurückgegebene Objekt (JSONObject) für bestimmte Eigenschaften keinen Getter hat. Sie möchten dieses JSONObject nicht serialisieren, sondern ein POJO serialisieren. Also einfach das POJO zurückgeben.
Verweisen Sie auf diesen Link: https://stackoverflow.com/a/35822500/5039001
Wenn Sie eine json-serialisierte Zeichenfolge zurückgeben möchten, geben Sie einfach die Zeichenfolge zurück. Spring verwendet in diesem Fall StringHttpMessageConverter anstelle des JSON-Konverters.
quelle
Map<String,Object>
oder einProperties
Objekt zurückgebenDer Grund, warum Ihr aktueller Ansatz nicht funktioniert, liegt darin, dass Jackson standardmäßig zum Serialisieren und Deserialisieren von Objekten verwendet wird. Es weiß jedoch nicht, wie man das serialisiert
JSONObject
. Wenn Sie eine dynamische JSON-Struktur erstellen möchten, können Sie beispielsweise Folgendes verwendenMap
:@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; }
Dies führt zu der folgenden JSON-Antwort:
{ "key": "value", "foo": "bar", "aa": "bb" }
Dies ist etwas eingeschränkt, da das Hinzufügen untergeordneter Objekte möglicherweise etwas schwieriger wird. Jackson hat jedoch einen eigenen Mechanismus, indem er
ObjectNode
und verwendetArrayNode
. Um es zu verwenden, müssen SieObjectMapper
in Ihrem Dienst / Controller automatisch verdrahten . Dann können Sie verwenden:@GetMapping public ObjectNode sayHello() { ObjectNode objectNode = mapper.createObjectNode(); objectNode.put("key", "value"); objectNode.put("foo", "bar"); objectNode.put("number", 42); return objectNode; }
Mit diesem Ansatz können Sie untergeordnete Objekte und Arrays hinzufügen und alle verschiedenen Typen verwenden.
quelle
ObjectMapper
du automatisch verdrahten solltest (siehe den Absatz über meinem letzten Codefragment).java.util.HashMap
ist eine Kernfunktionalität von Java seit Java 1.2.Sie können entweder eine Antwort wie
String
von @vagaasen vorgeschlagen zurückgeben oderResponseEntity
das von Spring bereitgestellte Objekt wie unten verwenden. Auf diese Weise können Sie auch zurückkehren,Http status code
was beim Webservice-Aufruf hilfreicher ist.@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); } }
quelle
JSONObject
, aber da Spring Jackson verwendet, habe ich esHashMap
stattdessen in a geändert, und dann hat der Code, den ich in dieser Antwort gelesen habe, funktioniert.Sie können hierfür auch eine Hashmap verwenden
@GetMapping public HashMap<String, Object> get() { HashMap<String, Object> map = new HashMap<>(); map.put("key1", "value1"); map.put("results", somePOJO); return map; }
quelle
@RequestMapping("/api/status") public Map doSomething() { return Collections.singletonMap("status", myService.doSomething()); }
PS. Funktioniert nur für 1 Wert
quelle
verwenden
ResponseEntity<ResponseBean>
Hier können Sie ResponseBean oder eine beliebige Java-Bean verwenden, um Ihre API-Antwort zurückzugeben. Dies ist die beste Vorgehensweise. Ich habe Enum als Antwort verwendet. Es gibt den Statuscode und die Statusmeldung der API zurück.
@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); }
für die Antwort ServiceStatus oder (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; } }
Die Spring REST-API sollte als Antwort den folgenden Schlüssel haben
Sie erhalten unten die endgültige Antwort
{ "StatusCode" : "0", "Message":"Login success" }
Sie können ResponseBody (Java POJO, ENUM usw.) gemäß Ihren Anforderungen verwenden.
quelle
Richtigere DTO-Erstellung für API-Abfragen, z. B. entityDTO:
Wenn Sie jedoch unterschiedliche Map-Parameter zurückgeben müssen, können Sie die nächsten beiden Beispiele verwenden.
2. Für die Rückgabe eines Parameters wie map:
quelle
Wenn Sie ein JSON-Objekt mit einem String zurückgeben müssen, sollte Folgendes funktionieren:
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); } ... }
quelle