Весенняя загрузка проблемы сериализации java.время.LocalDateTime с Джексоном для возврата временных меток ISO-8601 JSON?
я работаю над преобразованием некоторых моделей в приложение spring-boot REST API для использования java 8 java.time.LocalDateTime
вместо джоды DateTime
. Я хочу, чтобы метки времени, возвращенные из вызова API, придерживались . Мотивация должна быть совместима со временем Java 8 (здесь).
часть, которая оказывается сложной, когда дело доходит до сериализации объекта, содержащего LocalDateTime
в JSON.
например, у меня есть следующие сущность:
// ... misc imports
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@Data
@Entity
@Table(name = "users")
public class User {
@Id @Column
private String id;
@Column
private String name;
@Column
private String email;
@Column
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "UTC")
private java.time.LocalDateTime createdAt;
public User(String name, String email) {
this.id = Utils.generateUUID();
this.createdAt = LocalDateTime.now(ZoneOffset.UTC);
}
}
я также установил мой application.properties
отключить нужные в качестве метки Джексон:
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
мой maven deps:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.1.Final</version>
</dependency>
наконец, я пытаюсь получить представление JSON через контроллер:
@RequestMapping("/users")
@RestController
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping(
value = "/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public User getUser(@PathVariable("id") String id) {
return userService.findById(id);
}
}
когда я фактически делаю вызов этой конечной точке, я получаю следующее исключение:
java.lang.NoSuchMethodError:
com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value;
поочередно я также настроил приложение ObjectMapper
в конфигурации класс:
@Configuration
public class ServiceConfiguration {
@Bean
public ObjectMapper getJacksonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(
com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
false
);
return objectMapper;
}
}
все руководства значительно будут оценены.
обновление:
оказывается, это было несоответствие версии между версией Джексона Spring Boot и той, которую я имел в своем pom.xml
. Как предложили Милош и Энди, как только я установил правильную версию и запустил приложение с spring.jackson.serialization.write_dates_as_timestamps=true
, проблема была решена, без необходимости настраивать ObjectMapper
или добавление аннотаций на my LocalDateTime
модель поля.
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
</dependencies>
3 ответов
The NoSuchMethodError
- это потому, что вы смешиваете версии Джексона. Spring Boot 1.3.6 использует Jackson 2.6.7, и вы используете 2.8.1 из jackson-datatype-jsr310
.
Spring Boot обеспечивает управление зависимостями для Jackson, включая jackson-datatype-jsr310
, поэтому вы должны удалить версию из своего pom. Если вы хотите использовать другую версию Jackson, вы должны переопределить jackson.version
свойства:
<properties>
<jackson.version>2.8.1</jackson.version>
</properties>
это гарантирует, что все ваши зависимости Джексона имеют одинаковую версию, тем самым избегая проблемы с несовпадением версий.
вы также можете, если хотите, удалить свой Java-код, который настраивает ObjectMapper
. Модуль времени Java будет автоматически зарегистрирован, когда он находится в пути к классам, и даты записи в качестве временных меток могут быть настроены в application.properties
:
spring.jackson.serialization.write-dates-as-timestamps=false
код ObjectMapper
Боб должен быть помечен как @Primary
для того, чтобы быть подобран к весне. Кроме того, вы можете просто создать JavaTimeModule
bean, и он будет подобран весной и добавлен в сопоставитель объектов по умолчанию.
вы, вероятно, уже видели его, но взгляните на официальную документацию.
ошибка возникает из-за смешивания версий Jackson. Вы используете версию 1.3.6.RELEASE
Весна загрузки. Если вы перейдете на версию Spring Boot 2.x.x.RELEASE
затем вы можете заменить com.fasterxml.jackson.datatype
зависимость с помощью spring-boot-starter-json
зависимость. Таким образом, Вы позволяете Spring Boot заботиться о правильной версии Jackson.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>