Java 使用Spring和Jackson实现JSON双重序列化
我已经决定对我的所有实体使用DTO,这样我就不必使用@JSONIgnore注释来忽略JSON中的一些脆弱数据,如ID、用户密码等。我不确定这是否是正确的方法,但我想不出任何其他方法-如果你碰巧知道更好的方法,请告诉我 但说到这里,我有一个Book entity,它在其他字段中有一个价格-这是我将来唯一想更改的字段,标题/isbn等。不要更改(我知道它们不是一成不变的,但这是因为JPA-它需要setters/getter/非final字段,对吗?) Book.java(getter/setter命令): 我决定创建BookDTO,这样我在发布新书时就不必发送ID(这样Jackson可以毫无怨言地反序列化我的JSON) 所以我将价格存储为BigDecimal,但我认为我可以在JSON中使用double,然后只使用Java 使用Spring和Jackson实现JSON双重序列化,java,json,spring,hibernate,dto,Java,Json,Spring,Hibernate,Dto,我已经决定对我的所有实体使用DTO,这样我就不必使用@JSONIgnore注释来忽略JSON中的一些脆弱数据,如ID、用户密码等。我不确定这是否是正确的方法,但我想不出任何其他方法-如果你碰巧知道更好的方法,请告诉我 但说到这里,我有一个Book entity,它在其他字段中有一个价格-这是我将来唯一想更改的字段,标题/isbn等。不要更改(我知道它们不是一成不变的,但这是因为JPA-它需要setters/getter/非final字段,对吗?) Book.java(getter/setter命
BigDecimal.valueOf(double newPrice)
来更改Book实体的价格
这是我的BookController.java:
@RestController
public class BookController {
private final BookService bookService;
@Autowired
public BookController(BookService bookService) {
this.bookService = bookService;
}
@PutMapping("/books/{id}")
public ResponseEntity<?> editToDo(@PathVariable("id") Long id, @RequestBody double newPrice)
return new ResponseEntity<>(bookService.changePrice(id, newPrice), HttpStatus.OK);
}
@Service
@Transactional
public class BookService {
private final BookRepository bookRepository;
@Autowired
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
public Book addNewBook(BookDTO bookDTO) {
if (bookRepository.findByIsbn(bookDTO.getIsbn()).isPresent()) {
throw new BookException(
String.format("Book with that ISBN already exists in database: %s", bookDTO.getIsbn()));
}
Book book = new Book();
book.setAuthor(bookDTO.getAuthor());
book.setGenre(bookDTO.getGenre());
book.setIsbn(bookDTO.getIsbn());
book.setPrice(bookDTO.getPrice());
book.setPublicationYear(bookDTO.getPublicationYear());
book.setTitle(bookDTO.getTitle());
return bookRepository.save(book);
}
public Book changePrice(Long id, double price) {
Book book = findBookById(id);
book.setPrice(BigDecimal.valueOf(price));
return book;
}
public void deleteBook(Long id) {
bookRepository.delete(findBookById(id));
}
private Book findBookById(Long id) {
if (bookRepository.findOne(id) == null) {
throw new BookException(
String.format("Book with that ID doesn't exist in the database: %s", id));
}
return bookRepository.findOne(id);
}
}
当我用{'price':30.00}
发布@localhost:8080/books/1时,我得到了以下错误:
2017-03-07 13:12:11.502 INFO 8327 --- [nio-8080-exec-2] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:471) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar:8.5.11]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
2017-03-07 13:12:14.635 INFO 8327 --- [nio-8080-exec-3] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
2017-03-07 13:12:38.529 WARN 8327 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]
2017-03-07 13:12:38.529 WARN 8327 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]
2017-03-07 13:13:23.069 WARN 8327 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]
2017-03-07 13:13:23.069 WARN 8327 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]
不是关于你问的问题,但是如果你可以毫无问题地使用
BigDecimal.valueOf(double newPrice)
,你可能根本不需要BigDecimal…使用BigDecimal
可能是一种过度使用。在POST中出现错误的原因是单引号不是有效的json,您需要使用{“price”:30.00}
您可以显示bookDTO的setter和getter吗?若要,可能会将双值作为字符串发送。
@Service
@Transactional
public class BookService {
private final BookRepository bookRepository;
@Autowired
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
public Book addNewBook(BookDTO bookDTO) {
if (bookRepository.findByIsbn(bookDTO.getIsbn()).isPresent()) {
throw new BookException(
String.format("Book with that ISBN already exists in database: %s", bookDTO.getIsbn()));
}
Book book = new Book();
book.setAuthor(bookDTO.getAuthor());
book.setGenre(bookDTO.getGenre());
book.setIsbn(bookDTO.getIsbn());
book.setPrice(bookDTO.getPrice());
book.setPublicationYear(bookDTO.getPublicationYear());
book.setTitle(bookDTO.getTitle());
return bookRepository.save(book);
}
public Book changePrice(Long id, double price) {
Book book = findBookById(id);
book.setPrice(BigDecimal.valueOf(price));
return book;
}
public void deleteBook(Long id) {
bookRepository.delete(findBookById(id));
}
private Book findBookById(Long id) {
if (bookRepository.findOne(id) == null) {
throw new BookException(
String.format("Book with that ID doesn't exist in the database: %s", id));
}
return bookRepository.findOne(id);
}
}
2017-03-07 13:12:11.502 INFO 8327 --- [nio-8080-exec-2] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:471) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar:8.5.11]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
2017-03-07 13:12:14.635 INFO 8327 --- [nio-8080-exec-3] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
2017-03-07 13:12:38.529 WARN 8327 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]
2017-03-07 13:12:38.529 WARN 8327 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@61fe4c68; line: 1, column: 1]
2017-03-07 13:13:23.069 WARN 8327 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]
2017-03-07 13:13:23.069 WARN 8327 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
at [Source: java.io.PushbackInputStream@6e8cb870; line: 1, column: 1]