问题
I'm creating a simple rest controller with Spring Boot and the Web dependency. I'm trying to deserialize a JSON body to a test POJO with only 3 fields, but when I attempt to make a POST request, the server responds with a 500 error and the error I get in the console is:
.w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class java.util.LinkedHashMap
All of the code I have written is as follows:
EmailApplication.java:
package com.test.email.app;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = { "com.test.email" })
public class EmailApplication {
public static void main(String[] args) {
SpringApplication.run(EmailApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("----- You're up and running with test-email-app! -----");
};
}
}
EmailController.java:
package com.test.email.controller;
import com.test.email.entity.TestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import java.net.URI;
@RestController
public class EmailController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
TestEntity entity = new TestEntity();
return "test-email-app index";
}
@RequestMapping(value = "/poster", method = RequestMethod.POST)
public ResponseEntity<String> poster(@RequestBody TestEntity testEntity) {
URI location = URI.create("/poster");
return ResponseEntity.created(location).body(testEntity.getUrl());
}
}
TestEntity.java
package com.test.email.entity;
/**
* An entity for serialization/deserialization testing
*/
public class TestEntity {
public String url;
public int count;
public double height;
public TestEntity() {}
public TestEntity(String url, int count, double height) {
this.url = url;
this.count = count;
this.height = height;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
I'm making a POST request with Postman using only the header Content-Type: application/json
and with the body:
{ "url": "http://google.com", "count": 3, "height": 2.4 }
I don't know why Spring can't convert from a LinkedHashMap to my POJO. Any help would be appreciated.
Edit:
My pom.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test.email</groupId>
<artifactId>test-email-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test-email-app</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
回答1:
After Analyzing your problem, I found some cases where this issue can arise. Those are given bellow:
- Inner Class:
If your class TestEntity
is Inner class of your endpoint.
Just transfer your TestEntity
from Inner class to a separate class and run your code, it will work.
- Support Inner Class:
If you want to support inner class a RequestBody then make TestEntity
class as static, this will solve your problem.
- Spring dependency configuration:
If still not solved your problem, check your dependency on pom.xml
. May be you are not adding dependency on proper way. For this you can view this answer . Or you can add jackson
explicitly in your pom.xml
file.
Dependencies are:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
Hope this will solve your problem :)
If still not solved your problem, check some youtube video or some blog site or download some open-source project from github.
Thanks :)
Related links: Spring @Requestbody not mapping to inner class
回答2:
Try to specify that your method consumes JSON. Change your annotation:@RequestMapping(value = "/poster", method = RequestMethod.POST)
to
@PostMapping(value = "/poster",
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
produces = MediaType.TEXT_HTML)
The main part here that you specify that you expect your input to be JSON. Not sure what type you return but you can specify appropriate type or remove "produces" part. The main part is to specify what your input is
回答3:
Ideally this code should work but give a try by adding below dependency in pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.0</version>
</dependency>
来源:https://stackoverflow.com/questions/51411458/spring-tries-to-deserialize-to-linkedhashmap-instead-of-pojo