У меня есть образец RestController в Spring Boot:
@RestController
@RequestMapping("/api")
class MyRestController
{
@GetMapping(path = "/hello")
public JSONObject sayHello()
{
return new JSONObject("{'aa':'bb'}");
}
}
Я использую библиотеку JSON org.json
Когда я нажимаю API /hello
, я получаю исключение:
Servlet.service () для сервлета [dispatcherServlet] в контексте с path [] выдал исключение [Ошибка обработки запроса; вложенное исключение - java.lang.IllegalArgumentException: не найден преобразователь для возвращаемого значения типа: class org.json.JSONObject] с основной причиной
java.lang.IllegalArgumentException: не найден преобразователь для возвращаемого значения типа: class org.json.JSONObject
В чем проблема? Может кто-нибудь объяснить, что именно происходит?
java
json
spring-boot
response
ивекеси
источник
источник
@GetMapping(path = "/hello") @ResponseBody public String sayHello() {return"{'aa':'bb'}";}
Ответы:
Поскольку вы используете Spring Boot Web, зависимость Джексона неявна, и нам не нужно определять ее явно. Вы можете проверить зависимость Джексона
pom.xml
на вкладке иерархии зависимостей, если используете eclipse.И, как вы отметили,
@RestController
нет необходимости выполнять явное преобразование json. Просто верните POJO, и сериализатор Джексона позаботится о преобразовании в json. Это эквивалентно@ResponseBody
использованию с @Controller. Вместо того, чтобы размещать@ResponseBody
метод для каждого контроллера, мы размещаем его@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 будет использовать StringHttpMessageConverter вместо конвертера JSON.
источник
Map<String,Object>
илиProperties
объектПричина, по которой ваш текущий подход не работает, заключается в том, что Джексон по умолчанию используется для сериализации и десериализации объектов. Однако он не знает, как сериализовать
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" }
Это немного ограничено, поскольку добавить дочерние объекты может стать немного сложнее. Однако у Джексона есть собственный механизм, использующий
ObjectNode
иArrayNode
. Чтобы использовать его, вам необходимо выполнить автоматическое подключениеObjectMapper
в вашем сервисе / контроллере. Тогда вы можете использовать:@GetMapping public ObjectNode sayHello() { ObjectNode objectNode = mapper.createObjectNode(); objectNode.put("key", "value"); objectNode.put("foo", "bar"); objectNode.put("number", 42); return objectNode; }
Этот подход позволяет добавлять дочерние объекты, массивы и использовать все различные типы.
источник
ObjectMapper
вам следует автоматически подключить (см. абзац над моим последним фрагментом кода).java.util.HashMap
- это основная функциональность Java, начиная с Java 1.2.Вы можете либо вернуть ответ, как
String
предложено @vagaasen, либо использоватьResponseEntity
объект, предоставленный Spring, как показано ниже. Таким образом вы также можете вернуться,Http status code
что более полезно при вызове веб-службы.@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); } }
источник
JSONObject
, но поскольку Spring использует Jackson, я заменил его на a,HashMap
а затем код, который я прочитал в этом ответе, сработал.вы также можете использовать хэш-карту для этого
@GetMapping public HashMap<String, Object> get() { HashMap<String, Object> map = new HashMap<>(); map.put("key1", "value1"); map.put("results", somePOJO); return map; }
источник
@RequestMapping("/api/status") public Map doSomething() { return Collections.singletonMap("status", myService.doSomething()); }
PS. Работает только для 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 должен иметь в ответе ключ ниже
вы получите окончательный ответ ниже
{ "StatusCode" : "0", "Message":"Login success" }
вы можете использовать ResponseBody (java POJO, ENUM и т. д.) в соответствии с вашими требованиями.
источник
Правильнее создать DTO для запросов API, например entityDTO:
Но если вам нужно вернуть разные параметры карты, вы можете использовать следующие два примера
2. Для возврата одного параметра, такого как карта:
источник
Если вам нужно вернуть объект JSON с помощью String, тогда должно работать следующее:
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); } ... }
источник