Spring boot 控制器调用不支持内容类型“application/json;charset=UTF-8”
Posted
技术标签:
【中文标题】Spring boot 控制器调用不支持内容类型“application/json;charset=UTF-8”【英文标题】:Content type 'application/json;charset=UTF-8' not supported with Spring boot controller call 【发布时间】:2021-04-12 01:45:16 【问题描述】:我在将数据从我的 Angular 表单发送到我的 Spring 启动控制器时遇到问题: 我收到此错误: ** WARN 15020 --- [nio-8181-exec-2] .cjMappingJackson2HttpMessageConverter:无法评估 Jackson 反序列化类型 [[simple type, class com.biblio.fr.biblio.entite.BookDTO]]:org.springframework.beans .factory.BeanCreationException:创建名为“com.biblio.fr.biblio.entite.BookDTODeserializer”的bean时出错:bean实例化失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [com.biblio.fr.biblio.entite.BookDTODeserializer]:未找到默认构造函数;嵌套异常是 java.lang.NoSuchMethodException: com.biblio.fr.biblio.entite.BookDTODeserializer.()
WARN 15020 --- [nio-8181-exec-2] .cjMappingJackson2HttpMessageConverter:无法评估类型 [[simple type, class com.biblio.fr.biblio.entite.BookDTO]] 的 Jackson 反序列化:com。 fastxml.jackson.databind.JsonMappingException:com.biblio.fr.biblio.entite.BookDTODeserializer 类没有默认(无 arg)构造函数
WARN 15020 --- [nio-8181-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : 已解决 [org.springframework.web.HttpMediaTypeNotSupportedException: 内容类型 'application/json;charset=UTF-8' 不支持] **
这是我的java代码:
@RequestMapping(value = "/addBook", method = RequestMethod.POST, produces = "application/json")
@ApiOperation(value = "Add a new Book in the Library", response = BookDTO.class)
@ApiResponses(value = @ApiResponse(code = 409, message = "Conflict: the book already exist"),
@ApiResponse(code = 201, message = "Created: the book is successfully inserted"),
@ApiResponse(code = 304, message = "Not Modified: the book is unsuccessfully inserted") )
public ResponseEntity<BookDTO> createNewBook(@RequestBody BookDTO bookDTORequest)
// , UriComponentsBuilder uriComponentBuilder
Book existingBook = bookService.findBookByIsbn(bookDTORequest.getIsbn());
if (existingBook != null)
return new ResponseEntity<BookDTO>(HttpStatus.CONFLICT);
Book bookRequest = mapBookDTOToBook(bookDTORequest);
Book book = bookService.saveBook(bookRequest);
if (book != null && book.getId() != null)
BookDTO bookDTO = mapBookToBookDTO(book);
return new ResponseEntity<BookDTO>(bookDTO, HttpStatus.CREATED);
return new ResponseEntity<BookDTO>(HttpStatus.NOT_MODIFIED);
private BookDTO mapBookToBookDTO(Book book)
ModelMapper mapper = new ModelMapper();
BookDTO bookDTO = mapper.map(book, BookDTO.class);
if (book.getCategory() != null)
bookDTO.setCategory(new CategoryDTO(book.getCategory().getCode(), book.getCategory().getLabel()));
return bookDTO;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(using = BookDTODeserializer.class)
@Data
@AllArgsConstructors
public class BookDTO implements Comparable<BookDTO>
@ApiModelProperty(value = "Book id")
private Integer id;
@ApiModelProperty(value = "Book title")
private String title;
@ApiModelProperty(value = "Book isbn")
private String isbn;
@ApiModelProperty(value = "Book release date by the editor")
private LocalDate releaseDate;
@ApiModelProperty(value = "Book register date in the library")
private LocalDate registerDate;
@ApiModelProperty(value = "Book total examplaries")
private Integer totalExamplaries;
@ApiModelProperty(value = "Book author")
private String author;
@ApiModelProperty(value = "Book category")
private CategoryDTO category;
@Override
public int compareTo(BookDTO o)
return title.compareToIgnoreCase(o.getTitle());
public BookDTO()
super();
@Entity
@Data
@AllArgsConstructors
public class Book
private static final long serialVersionUID = 425345L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String author;
private String publisher;
private String publicationDate;
private String language;
private String category;
private int numberOfPages;
private String format;
private String isbn;
private double shippingWeight;
private double listPrice;
private double ourPrice;
private boolean active = true;
@Column(columnDefinition = "text")
private String description;
private int inStockNumber;
@Transient
private MultipartFile bookImage;
@Data
@AllArgsConstructors
@JsonDeserialize(using = CategoryDTODeserializer.class)
public class CategoryDTO implements Comparable<CategoryDTO>
public CategoryDTO()
public CategoryDTO(String code, String label)
super();
this.code = code;
this.label = label;
@ApiModelProperty(value = "Category code")
private String code;
@ApiModelProperty(value = "Category label")
private String label;
@Entity
@Table(name = "CATEGORY")
public class Category
public Category()
public Category(String code, String label)
super();
this.code = code;
this.label = label;
private String code;
private String label;
@Id
@Column(name = "CODE")
public String getCode()
return code;
public void setCode(String code)
this.code = code;
@Column(name = "LABEL", nullable = false)
public String getLabel()
return label;
public void setLabel(String label)
this.label = label;
public class BookDTODeserializer extends StdDeserializer<BookDTO>
@Override
public BookDTO deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException
// TODO Auto-generated method stub
JsonNode node = p.getCodec().readTree(p);
Integer id = (Integer) ((IntNode) node.get("id")).numberValue();
String title = node.get("title").asText();
String isbn = node.get("isbn").asText();
LocalDate releaseDate = LocalDate.parse(node.get("releaseDate").asText());
LocalDate registerDate = LocalDate.parse(node.get("registerDate").asText());
Integer totalExamplaries = (Integer) ((IntNode) node.get("totalExamplaries")).numberValue();
String author = node.get("author").asText();
String codeCategory = node.get("code").asText();
String labelCategory = node.get("label").asText();
return new BookDTO(id, title, isbn, releaseDate, registerDate, totalExamplaries, author,
new CategoryDTO(codeCategory, labelCategory));
// return null;
public BookDTODeserializer(Class<?> vc)
super(vc);
// TODO Auto-generated constructor stub
public BookDTODeserializer(JavaType valueType)
super(valueType);
// TODO Auto-generated constructor stub
public BookDTODeserializer(StdDeserializer<?> src)
super(src);
// TODO Auto-generated constructor stub
public class CategoryDTODeserializer extends StdDeserializer<CategoryDTO>
@Override
public CategoryDTO deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException
JsonNode node = p.getCodec().readTree(p);
String codeCategory = node.get("code").asText();
String labelCategory = node.get("label").asText();
return new CategoryDTO(codeCategory, labelCategory);
public CategoryDTODeserializer(Class<?> vc)
super(vc);
// TODO Auto-generated constructor stub
public CategoryDTODeserializer(JavaType valueType)
super(valueType);
// TODO Auto-generated constructor stub
public CategoryDTODeserializer(StdDeserializer<?> src)
super(src);
// TODO Auto-generated constructor stub
还有我的角码
saveBook(book: Book): Observable<Book>
let headers = new HttpHeaders();
headers.append('content-type', 'application/json');
headers.append('accept', 'application/json');
return this.http.post<Book>(environment.apiUrl+'/rest/book/api/addBook', book, headers: headers);
有什么想法吗?
【问题讨论】:
【参考方案1】:根据警告/错误消息,您缺少以下内容:
-
未找到默认构造函数;嵌套异常是 java.lang.NoSuchMethodException: com.biblio.fr.biblio.entite.BookDTODeserializer
使用 @NoArgsConstructor 声明 BookDTODeserializer
-
也将消费添加为 JSON。
@RequestMapping(value = "/addBook", method = RequestMethod.POST,produces = "application/json", consumes = "application/json")
考虑到您已经在请求正文中以 JSON 形式接收 DTO,我不明白为什么需要这个“手动”反序列化器。
【讨论】:
嗨@EZequiel,我在 BookDTODeserializer 解析 localDate LocalDate releaseDate = LocalDate.parse(node.get("releaseDate").asText());Text '2021-01-14T00 时遇到错误: 00:00.000Z' 无法解析,在索引 10 处找到未解析的文本 嗨@obela06,您需要设置日期格式。对于您的情况,我找不到默认格式,因此建议使用模式: LocalDate.parse(node.get("releaseDate").asText(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'hh :mm:ss.nnn'Z'"));【参考方案2】:Spring 引导控制器调用不支持内容类型 'application/json;charset=UTF-8'
不是这里的问题
问题是:
com.biblio.fr.biblio.entite.BookDTODeserializer 没有默认(无 arg)构造函数
public class BookDTODeserializer extends StdDeserializer<BookDTO>
public BookDTODeserializer()
super(BookDTO.class);
...
直接加@NoArgsConstructor
对你没有帮助,会报错:
There is no default constructor available in 'com.fasterxml.jackson.databind.deser.std.StdDeserializer'
【讨论】:
嗨@Hùng Phan Viêt,我在BookDTODeserializer 中遇到错误,无法解析localDate LocalDate releaseDate = LocalDate.parse(node.get("releaseDate").asText());Text '2021-01- 14T00:00:00.000Z' 无法解析,在索引 10 处找到未解析的文本以上是关于Spring boot 控制器调用不支持内容类型“application/json;charset=UTF-8”的主要内容,如果未能解决你的问题,请参考以下文章
spring boot mvc - 不支持内容类型'application/json;charset = UTF-8'
内容类型'text/plain;charset = UTF-8'在RestController类中的spring boot中不支持错误
不支持 Spring/Postman 内容类型“application/octet-stream”