zav*_*ton 27 rest json jackson spring-data-rest spring-boot
我是Spring Data REST项目的新手,我正在尝试创建我的第一个RESTful服务.任务很简单,但我被困住了.
我想使用RESTful API对存储在嵌入式数据库中的用户数据执行CRUD操作.
但我无法弄清楚如何使Spring框架处理birthData为"1999-12-15"并将其存储为LocalDate.@JsonFormat注释没有帮助.
目前我收到错误:
HTTP/1.1 400
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 24 Aug 2017 13:36:51 GMT
Connection: close
{"cause":{"cause":null,"message":"Can not construct instance of java.time.LocalDate:
no String-argument constructor/factory method to deserialize from String value ('1999-10-10')\n
at [Source: org.apache.catalina.connector.CoyoteInputStream@4ee2a60e;
line: 1, column: 65] (through reference chain: ru.zavanton.entities.User[\"birthDate\"])"},
"message":"JSON parse error: Can not construct instance of java.time.LocalDate:
no String-argument constructor/factory method to deserialize from String value ('1999-10-10'); nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value ('1999-10-10')\n
at [Source: org.apache.catalina.connector.CoyoteInputStream@4ee2a60e; line: 1, column: 65] (through reference chain: ru.zavanton.entities.User[\"birthDate\"])"}
Run Code Online (Sandbox Code Playgroud)
如何使其工作,以便客户端调用如下:
curl -i -X POST -H "Content-Type:application/json" -d "{ \"firstName\" : \"John\", \"lastName\" : \"Johnson\", \"birthDate\" : \"1999-10-10\", \"email\" : \"john@example.com\" }" http://localhost:8080/users
Run Code Online (Sandbox Code Playgroud)
实际上会将实体存储到数据库中.
以下是有关课程的信息.
用户类:
package ru.zavanton.entities;
import com.fasterxml.jackson.annotation.JsonFormat;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDate;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthDate;
private String email;
private String password;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDate getBirthDate() {
return birthDate;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Run Code Online (Sandbox Code Playgroud)
UserRepository类:
package ru.zavanton.repositories;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import ru.zavanton.entities.User;
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
User findByEmail(@Param("email") String email);
}
Run Code Online (Sandbox Code Playgroud)
申请类:
package ru.zavanton;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
San*_*tKD 36
你需要jackson依赖这个序列化和反序列化.
添加此依赖项:
摇篮:
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.4")
Run Code Online (Sandbox Code Playgroud)
Maven的:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
之后,您需要告诉Jackson ObjectMapper使用JavaTimeModule.为此,在主类中自动装配ObjectMapper并向其注册JavaTimeModule.
import javax.annotation.PostConstruct;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@SpringBootApplication
public class MockEmployeeApplication {
@Autowired
private ObjectMapper objectMapper;
public static void main(String[] args) {
SpringApplication.run(MockEmployeeApplication.class, args);
}
@PostConstruct
public void setUp() {
objectMapper.registerModule(new JavaTimeModule());
}
}
Run Code Online (Sandbox Code Playgroud)
之后,应正确序列化和反序列化您的LocalDate和LocalDateTime.
Spi*_*der 25
摇篮(build.gradle):
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
Run Code Online (Sandbox Code Playgroud)
实体(User.class):
LocalDate dateOfBirth;
Run Code Online (Sandbox Code Playgroud)
代码:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
User user = mapper.readValue(json, User.class);
Run Code Online (Sandbox Code Playgroud)
Mat*_*een 21
我有一个类似的问题,我通过进行两次更改来解决
application.yaml
文件中添加以下条目spring:
jackson:
serialization.write_dates_as_timestamps: false
Run Code Online (Sandbox Code Playgroud)
LocalDate
字段中添加以下两个注释@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
Run Code Online (Sandbox Code Playgroud)
例子
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
public class Customer {
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
protected LocalDate birthdate;
}
Run Code Online (Sandbox Code Playgroud)
示例请求格式:
{"birthdate": "2019-11-28"}
Run Code Online (Sandbox Code Playgroud)
示例请求格式为数组
{"birthdate":[2019,11,18]}
Run Code Online (Sandbox Code Playgroud)
zav*_*ton 13
事实证明,不应该忘记将jacson依赖包含到pom文件中.这解决了我的问题:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我刚刚为此奋斗了3个小时。我相信 Dherik 的答案(关于 AMQP 的奖励材料)让我离我的答案 YMMV 很近。
我在 SpringBootApplication 的对象映射器中注册了 JavaTimeModule,如下所示:
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
Run Code Online (Sandbox Code Playgroud)
然而,通过 STOMP 连接传入的 Instant 仍然没有反序列化。然后我意识到我无意中创建了一个 MappingJackson2MessageConverter,它创建了第二个 ObjectMapper。所以我想这个故事的寓意是:你确定你已经调整了所有的 ObjectMappers 吗?就我而言,我将 MappingJackson2MessageConverter.objectMapper 替换为注册了 JavaTimeModule 的外部版本,一切都很好:
@Autowired
ObjectMapper objectMapper;
@Bean
public WebSocketStompClient webSocketStompClient(WebSocketClient webSocketClient,
StompSessionHandler stompSessionHandler) {
WebSocketStompClient webSocketStompClient = new WebSocketStompClient(webSocketClient);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(objectMapper);
webSocketStompClient.setMessageConverter(converter);
webSocketStompClient.connect("http://localhost:8080/myapp", stompSessionHandler);
return webSocketStompClient;
}
Run Code Online (Sandbox Code Playgroud)
好吧,我在每个项目上所做的都是上述选项的混合。
首先,添加jsr310依赖:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
重要细节:将此依赖项放在依赖项列表的顶部。我已经看到一个项目,即使对 pom.xml 有这种依赖性,Localdate 错误仍然存在。但是改变依赖的顺序错误消失了。
在您的/src/main/resources/application.yml
文件上,设置write-dates-as-timestamps
属性:
spring:
jackson:
serialization:
write-dates-as-timestamps: false
Run Code Online (Sandbox Code Playgroud)
并创建一个ObjectMapper
bean,如下所示:
@Configuration
public class WebConfigurer {
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return objectMapper;
}
}
Run Code Online (Sandbox Code Playgroud)
按照此配置,转换始终在 Spring Boot 1.5.x 上正常工作,不会出现任何错误。
使用 Spring AMQP,请注意您是否有一个新实例Jackson2JsonMessageConverter
(创建 时常见的事情SimpleRabbitListenerContainerFactory
)。您需要将ObjectMapper
bean传递给它,例如:
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(objectMapper);
Run Code Online (Sandbox Code Playgroud)
否则,您将收到相同的错误。
归档时间: |
|
查看次数: |
48382 次 |
最近记录: |