Tengo un RestController de muestra en Spring Boot:
@RestController
@RequestMapping("/api")
class MyRestController
{
@GetMapping(path = "/hello")
public JSONObject sayHello()
{
return new JSONObject("{'aa':'bb'}");
}
}
Estoy usando la biblioteca JSON org.json
Cuando presiono API /hello, obtengo una excepción que dice:
Servlet.service () para servlet [dispatcherServlet] en contexto con la ruta [] arrojó una excepción [El procesamiento de la solicitud falló; La excepción anidada es java.lang.IllegalArgumentException: No se encontró un convertidor para el valor de retorno del tipo: class org.json.JSONObject] con la causa raíz.
java.lang.IllegalArgumentException: No se encontró ningún convertidor para el valor de retorno del tipo: class org.json.JSONObject
¿Cual es el problema? ¿Alguien puede explicar qué está sucediendo exactamente?
java
json
spring-boot
response
iwekesi
fuente
fuente

@GetMapping(path = "/hello") @ResponseBody public String sayHello() {return"{'aa':'bb'}";}Respuestas:
Como está utilizando la web Spring Boot, la dependencia de Jackson es implícita y no tenemos que definirla explícitamente. Puede verificar la dependencia de Jackson en su
pom.xmlen la pestaña de jerarquía de dependencia si usa eclipse.Y como ha anotado,
@RestControllerno es necesario realizar una conversión json explícita. Simplemente devuelva un POJO y el serializador jackson se encargará de convertir a json. Es equivalente a usar@ResponseBodycuando se usa con @Controller. En lugar de colocar@ResponseBodyen cada método de controlador, colocamos en lugar@RestControllerde vainilla@Controllery,@ResponseBodyde forma predeterminada, se aplica a todos los recursos en ese controlador.Consulte este enlace: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
El problema al que se enfrenta es porque el objeto devuelto (JSONObject) no tiene getter para ciertas propiedades. Y su intención no es serializar este JSONObject, sino serializar un POJO. Así que devuelve el POJO.
Consulte este enlace: https://stackoverflow.com/a/35822500/5039001
Si desea devolver una cadena serializada json, simplemente devuelva la cadena. Spring usará StringHttpMessageConverter en lugar del convertidor JSON en este caso.
fuente
Map<String,Object>unPropertiesobjeto o un objetoLa razón por la que su enfoque actual no funciona es porque Jackson se usa de forma predeterminada para serializar y deserializar objetos. Sin embargo, no sabe cómo serializar
JSONObject. Si desea crear una estructura JSON dinámica, puede usarMap, por ejemplo:@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; }Esto conducirá a la siguiente respuesta JSON:
{ "key": "value", "foo": "bar", "aa": "bb" }Esto es un poco limitado, ya que puede resultar un poco más difícil agregar objetos secundarios. Sin embargo, Jackson tiene su propio mecanismo, usando
ObjectNodeyArrayNode. Para usarlo, debe realizar un autowireObjectMapperen su servicio / controlador. Entonces puedes usar:@GetMapping public ObjectNode sayHello() { ObjectNode objectNode = mapper.createObjectNode(); objectNode.put("key", "value"); objectNode.put("foo", "bar"); objectNode.put("number", 42); return objectNode; }Este enfoque le permite agregar objetos secundarios, matrices y usar todos los tipos.
fuente
ObjectMapperque debe conectar automáticamente (consulte el párrafo anterior a mi último fragmento de código).java.util.HashMapes una funcionalidad central de Java desde Java 1.2.Puede devolver una respuesta como
Stringlo sugiere @vagaasen o puede usar elResponseEntityObjeto proporcionado por Spring como se muestra a continuación. De esta manera, también puede devolver loHttp status codeque es más útil en la llamada de servicio 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); } }fuente
JSONObject, pero como Spring usa Jackson, lo cambié a aHashMapy luego el código que leí en esta respuesta funcionó.también puedes usar un mapa de hash para esto
@GetMapping public HashMap<String, Object> get() { HashMap<String, Object> map = new HashMap<>(); map.put("key1", "value1"); map.put("results", somePOJO); return map; }fuente
@RequestMapping("/api/status") public Map doSomething() { return Collections.singletonMap("status", myService.doSomething()); }PD. Funciona solo por 1 valor
fuente
utilizar
ResponseEntity<ResponseBean>Aquí puede usar ResponseBean o Any Java Bean como desee para devolver su respuesta de API y es la mejor práctica. He usado Enum como respuesta. devolverá el código de estado y el mensaje de estado de la 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); }para respuesta ServiceStatus o (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 debe tener la siguiente clave en respuesta
obtendrá la respuesta final a continuación
{ "StatusCode" : "0", "Message":"Login success" }puede utilizar ResponseBody (java POJO, ENUM, etc.) según sus necesidades.
fuente
Más correcto crear DTO para consultas de API, por ejemplo entityDTO:
Pero si necesita devolver diferentes parámetros de Map, puede usar los dos ejemplos siguientes
2. Para devolver un parámetro como map:
fuente
Si necesita devolver un objeto JSON usando una cadena, lo siguiente debería funcionar:
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); } ... }fuente