Притвориться Джексон dateTime JsonMappingException - PullRequest
0 голосов
/ 06 марта 2019

У меня есть две службы, которые взаимодействуют с openfeign (github.openfeign: 10.2.0).Я навязываю проблему с десериализацией datatime, которая отправляется как JSON.Вот моя конфигурация:

@Configuration
class JacksonConfig : WebMvcConfigurerAdapter() {
    override fun extendMessageConverters(converters: List<HttpMessageConverter<*>>?) {
        for (converter in converters!!) {
            if (converter is MappingJackson2HttpMessageConverter) {
                val objectMapper = converter.objectMapper
                objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                objectMapper.disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
                break
            }
        }
    }
}
    private val client = Feign.builder()
        .encoder(JacksonEncoder())
        .decoder(JacksonDecoder())
        .target(Client::class.java, host)

@JsonIgnoreProperties(ignoreUnknown = true)
data class XYZ(
  var id: Int? = null,
  val X: Int? = null,
  val Y: Int? = null,
  @Enumerated(EnumType.STRING)
  val z: Type? = null,
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")
  val createdOn: LocalDateTime? = null
)

Вот исключение:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.FeignException: Can not construct instance of java.time.LocalDateTime: no String-argument constructor/factory method to deserialize from String value ('2019-03-06T16:50:53')
  at [Source: java.io.BufferedReader@3c14b300; line: 1, column: 77] (through reference chain: java.util.HashSet[0]->XYZ["createdOn"]) reading GET http://localhost:8080/path] with root cause 
  com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.LocalDateTime: no String-argument constructor/factory method to deserialize from String value ('2019-03-06T16:50:53')
  at [Source: java.io.BufferedReader@3c14b300; line: 1, column: 77] (through reference chain: java.util.HashSet[0]->XYZ["createdOn"])

Вот Json:

[
  {
    "id": 2,
    "X": 1,
    "U": 1,
    "Z": "ABC",
    "createdOn": "2019-03-06T16:50:53"
  }
]

Зависимости:

    compile group: 'io.github.openfeign', name: 'feign-core', version: '10.2.0'
    compile group: 'io.github.openfeign', name: 'feign-jackson', version: '10.2.0'
    compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk:$jackson_version"
    compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
    compile "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_config"

1 Ответ

1 голос
/ 06 марта 2019

Когда мы посмотрим, как реализованы JacksonEncoder и JacksonDecoder, мы заметим, что они создают новый ObjectMapper в конструкторе:

public JacksonDecoder(Iterable<Module> modules) {
  this(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
      .registerModules(modules));
}

Выше конструктор вызывается по умолчанию с emptyList().Итак, нам нужно предоставить все модули, которые мы хотим использовать вручную.

Чтобы получить максимальную отдачу от Java 8 и Jackson, зарегистрируйте все 3 модуля из jackson-modules-java8 :

private val client = Feign.builder()
    .encoder(JacksonEncoder(Arrays.asList(JavaTimeModule(), ...)))
    .decoder(JacksonDecoder(Arrays.asList(JavaTimeModule(), ...)))
    .target(Client::class.java, host)

EDIT
Ther - конструктор, который позволяет использовать экземпляр ObjectMapper.Вы можете создать новый экземпляр или добавить его из своего контейнера:

val mapper = ObjectMapper()
mapper.registerModule(ParameterNamesModule())
   .registerModule(Jdk8Module())
   .registerModule(JavaTimeModule())
// other configuration

val client = Feign.builder()
    .encoder(JacksonEncoder(mapper))
    .decoder(JacksonDecoder(mapper))
    .target(Client::class.java, host)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...