Post 方法未读取 json,仅 Spring 引导中的字符串 api
Post method not reading json, only String in Spring Boot api
我正在开发一个简单的 CRUD api 但我的 post 方法不起作用,每次发送 json 格式的数据时都会抛出此异常
{
"title": "Cannot construct instance of `academy.devdojo.springboot2.requests.AnimePostRequestBody` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 2, column: 5]",
"status": 400,
"details": "JSON parse error: Cannot construct instance of `academy.devdojo.springboot2.requests.AnimePostRequestBody` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `academy.devdojo.springboot2.requests.AnimePostRequestBody` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 2, column: 5]",
"developerMessage": "org.springframework.http.converter.HttpMessageNotReadableException",
"timestamp": "2022-01-13T14:45:34.9138659"
}
它仅在发送一个简单的字符串(如“要保存的名称”)时有效,而不是
{
"name" : "some name to be saved"
}
这是我的 类
实体
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Builder
public class Anime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty(message= "anime name cannot be empty")
private String name;
}
回购
public interface AnimeRepository extends JpaRepository<Anime, Long> {
List<Anime> findByName(String name);
}
服务
@Service
@RequiredArgsConstructor
public class AnimeService {
private final AnimeRepository animeRepository;
public Page<Anime> listAll(Pageable pageable) {
return animeRepository.findAll(pageable);
}
public List<Anime> findByName(String name) {
List<Anime> byName = animeRepository.findByName(name);
if (byName.isEmpty()){
throw new BadRequestException("Anime not Found");
}
return byName;
}
public Anime findByIdOrThrowBadRequestException(long id) {
return animeRepository.findById(id)
.orElseThrow(() -> new BadRequestException("Anime not Found"));
}
public Anime save(AnimePostRequestBody animePostRequestBody) {
Anime anime = AnimeMapper.INSTANCE.toAnime(animePostRequestBody);
return animeRepository.save(anime);
}
public void delete(long id) {
animeRepository.delete(findByIdOrThrowBadRequestException(id));
}
public void replace(AnimePutRequestBody animePutRequestBody) {
Anime savedAnime = findByIdOrThrowBadRequestException(animePutRequestBody.getId());
Anime anime = AnimeMapper.INSTANCE.toAnime(animePutRequestBody);
anime.setId(savedAnime.getId());
animeRepository.save(anime);
}
public List<Anime> listAllNonPageable() {
return animeRepository.findAll();
}
}
休息控制器
@RestController
@Api(tags = "Atividades Economicas")
@RequestMapping("animes")
@Log4j2
@RequiredArgsConstructor
public class AnimeController {
private final DateUtil dateUtil;
private final AnimeService animeService;
@ApiOperation(value = "Listar todos")
@GetMapping
public ResponseEntity<Page<Anime>> list(Pageable pageable) {
//log.info(dateUtil.formatLocalDateTimeToDatabaseStyle(LocalDateTime.now()));
return ResponseEntity.ok(animeService.listAll(pageable));
}
@GetMapping(path = "/all")
public ResponseEntity<List<Anime>> listAll() {
//log.info(dateUtil.formatLocalDateTimeToDatabaseStyle(LocalDateTime.now()));
return ResponseEntity.ok(animeService.listAllNonPageable());
}
@ApiOperation(value = "Listar por ID")
@GetMapping(path = "/{id}")
public ResponseEntity<Anime> findById(@PathVariable long id) {
return ResponseEntity.ok(animeService.findByIdOrThrowBadRequestException(id));
}
@ApiOperation(value = "Encontrar pelo nome")
@GetMapping(path = "/find")
public ResponseEntity<List<Anime>> findByName(@RequestParam String name) {
return ResponseEntity.ok(animeService.findByName(name));
}
@PostMapping
public ResponseEntity<Anime> save(@RequestBody @Valid AnimePostRequestBody animePostRequestBody) {
return new ResponseEntity<>(animeService.save(animePostRequestBody), HttpStatus.CREATED);
}
@DeleteMapping(path = "/{id}")
public ResponseEntity<Void> delete(@PathVariable long id) {
animeService.delete(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@PutMapping
public ResponseEntity<Void> replace(@RequestBody AnimePutRequestBody animePutRequestBody) {
animeService.replace(animePutRequestBody);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
DTO
@Data
@Builder
public class AnimePostRequestBody {
@NotEmpty(message= "anime name cannot be empty")
private String name;
}
@Data
@Builder
public class AnimePutRequestBody {
private Long id;
private String name;
}
MAPPER
@Mapper(componentModel = "spring")
public abstract class AnimeMapper {
public static final AnimeMapper INSTANCE = Mappers.getMapper(AnimeMapper.class);
public abstract Anime toAnime(AnimePostRequestBody animePostRequestBody);
public abstract Anime toAnime(AnimePutRequestBody animePutRequestBody);
}
p.s。 put 方法工作正常,尽管它们非常相似。
@Data是一个便捷的快捷注解,将@ToString、@EqualsAndHashCode、@Getter/@Setter和@RequiredArgsConstructor的特性捆绑在一起
需要默认构造函数。添加lombok的@NoArgsConstructor注解。
连同模型 class,DTO class 还应包含 @AllArgsConstructor
和 @NoArgsConstructor
。要将 RequestBody 值映射到 DTO,它将需要构造函数,而 @Data 不提供 @AllArgsConstructor 和 @NoArgsConstructor 构造函数。
//实体
@Data
@Entity
@Table(name = "Anime")
@Builder
public class Anime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty(message= "anime name cannot be empty")
private String name;
}
//回购
@Repository
public interface AnimeRepository extends JpaRepository<Anime, Long> {
}
//DTO
@Getter
public class AnimePostRequestBody {
@NotEmpty(message = "anime name cannot by empty")
private String name;
}
//控制器
@RestController
@RequestMapping("animes")
public class AnimeController {
@Autowired
private AnimeService animeService;
@PostMapping
public ResponseEntity<Anime> save(@RequestBody @Valid AnimePostRequestBody animePostRequestBody) {
return new ResponseEntity<>(animeService.save(animePostRequestBody), HttpStatus.CREATED);
}
}
//服务
@Service
public class AnimeService {
@Autowired
private AnimeRepository animeRepository;
public Anime save(AnimePostRequestBody animePostRequestBody) {
Anime anime = Anime.builder()
.name(animePostRequestBody.getName())
.build();
return animeRepository.save(anime);
}
}
输出
{
“编号”:4,
“名称”:“火影忍者”
}
替换此行
public ResponseEntity<Anime> save(@RequestBody @Valid AnimePostRequestBody animePostRequestBody){..
有了这个:
public ResponseEntity<Anime> save(@Valid @RequestBody AnimePostRequestBody animePostRequestBody)
我正在开发一个简单的 CRUD api 但我的 post 方法不起作用,每次发送 json 格式的数据时都会抛出此异常
{
"title": "Cannot construct instance of `academy.devdojo.springboot2.requests.AnimePostRequestBody` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 2, column: 5]",
"status": 400,
"details": "JSON parse error: Cannot construct instance of `academy.devdojo.springboot2.requests.AnimePostRequestBody` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `academy.devdojo.springboot2.requests.AnimePostRequestBody` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 2, column: 5]",
"developerMessage": "org.springframework.http.converter.HttpMessageNotReadableException",
"timestamp": "2022-01-13T14:45:34.9138659"
}
它仅在发送一个简单的字符串(如“要保存的名称”)时有效,而不是
{
"name" : "some name to be saved"
}
这是我的 类
实体
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Builder
public class Anime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty(message= "anime name cannot be empty")
private String name;
}
回购
public interface AnimeRepository extends JpaRepository<Anime, Long> {
List<Anime> findByName(String name);
}
服务
@Service
@RequiredArgsConstructor
public class AnimeService {
private final AnimeRepository animeRepository;
public Page<Anime> listAll(Pageable pageable) {
return animeRepository.findAll(pageable);
}
public List<Anime> findByName(String name) {
List<Anime> byName = animeRepository.findByName(name);
if (byName.isEmpty()){
throw new BadRequestException("Anime not Found");
}
return byName;
}
public Anime findByIdOrThrowBadRequestException(long id) {
return animeRepository.findById(id)
.orElseThrow(() -> new BadRequestException("Anime not Found"));
}
public Anime save(AnimePostRequestBody animePostRequestBody) {
Anime anime = AnimeMapper.INSTANCE.toAnime(animePostRequestBody);
return animeRepository.save(anime);
}
public void delete(long id) {
animeRepository.delete(findByIdOrThrowBadRequestException(id));
}
public void replace(AnimePutRequestBody animePutRequestBody) {
Anime savedAnime = findByIdOrThrowBadRequestException(animePutRequestBody.getId());
Anime anime = AnimeMapper.INSTANCE.toAnime(animePutRequestBody);
anime.setId(savedAnime.getId());
animeRepository.save(anime);
}
public List<Anime> listAllNonPageable() {
return animeRepository.findAll();
}
}
休息控制器
@RestController
@Api(tags = "Atividades Economicas")
@RequestMapping("animes")
@Log4j2
@RequiredArgsConstructor
public class AnimeController {
private final DateUtil dateUtil;
private final AnimeService animeService;
@ApiOperation(value = "Listar todos")
@GetMapping
public ResponseEntity<Page<Anime>> list(Pageable pageable) {
//log.info(dateUtil.formatLocalDateTimeToDatabaseStyle(LocalDateTime.now()));
return ResponseEntity.ok(animeService.listAll(pageable));
}
@GetMapping(path = "/all")
public ResponseEntity<List<Anime>> listAll() {
//log.info(dateUtil.formatLocalDateTimeToDatabaseStyle(LocalDateTime.now()));
return ResponseEntity.ok(animeService.listAllNonPageable());
}
@ApiOperation(value = "Listar por ID")
@GetMapping(path = "/{id}")
public ResponseEntity<Anime> findById(@PathVariable long id) {
return ResponseEntity.ok(animeService.findByIdOrThrowBadRequestException(id));
}
@ApiOperation(value = "Encontrar pelo nome")
@GetMapping(path = "/find")
public ResponseEntity<List<Anime>> findByName(@RequestParam String name) {
return ResponseEntity.ok(animeService.findByName(name));
}
@PostMapping
public ResponseEntity<Anime> save(@RequestBody @Valid AnimePostRequestBody animePostRequestBody) {
return new ResponseEntity<>(animeService.save(animePostRequestBody), HttpStatus.CREATED);
}
@DeleteMapping(path = "/{id}")
public ResponseEntity<Void> delete(@PathVariable long id) {
animeService.delete(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@PutMapping
public ResponseEntity<Void> replace(@RequestBody AnimePutRequestBody animePutRequestBody) {
animeService.replace(animePutRequestBody);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
DTO
@Data
@Builder
public class AnimePostRequestBody {
@NotEmpty(message= "anime name cannot be empty")
private String name;
}
@Data
@Builder
public class AnimePutRequestBody {
private Long id;
private String name;
}
MAPPER
@Mapper(componentModel = "spring")
public abstract class AnimeMapper {
public static final AnimeMapper INSTANCE = Mappers.getMapper(AnimeMapper.class);
public abstract Anime toAnime(AnimePostRequestBody animePostRequestBody);
public abstract Anime toAnime(AnimePutRequestBody animePutRequestBody);
}
p.s。 put 方法工作正常,尽管它们非常相似。
@Data是一个便捷的快捷注解,将@ToString、@EqualsAndHashCode、@Getter/@Setter和@RequiredArgsConstructor的特性捆绑在一起
需要默认构造函数。添加lombok的@NoArgsConstructor注解。
连同模型 class,DTO class 还应包含 @AllArgsConstructor
和 @NoArgsConstructor
。要将 RequestBody 值映射到 DTO,它将需要构造函数,而 @Data 不提供 @AllArgsConstructor 和 @NoArgsConstructor 构造函数。
//实体
@Data
@Entity
@Table(name = "Anime")
@Builder
public class Anime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty(message= "anime name cannot be empty")
private String name;
}
//回购
@Repository
public interface AnimeRepository extends JpaRepository<Anime, Long> {
}
//DTO
@Getter
public class AnimePostRequestBody {
@NotEmpty(message = "anime name cannot by empty")
private String name;
}
//控制器
@RestController
@RequestMapping("animes")
public class AnimeController {
@Autowired
private AnimeService animeService;
@PostMapping
public ResponseEntity<Anime> save(@RequestBody @Valid AnimePostRequestBody animePostRequestBody) {
return new ResponseEntity<>(animeService.save(animePostRequestBody), HttpStatus.CREATED);
}
}
//服务
@Service
public class AnimeService {
@Autowired
private AnimeRepository animeRepository;
public Anime save(AnimePostRequestBody animePostRequestBody) {
Anime anime = Anime.builder()
.name(animePostRequestBody.getName())
.build();
return animeRepository.save(anime);
}
}
输出
{ “编号”:4, “名称”:“火影忍者” }
替换此行
public ResponseEntity<Anime> save(@RequestBody @Valid AnimePostRequestBody animePostRequestBody){..
有了这个:
public ResponseEntity<Anime> save(@Valid @RequestBody AnimePostRequestBody animePostRequestBody)