com.fasterxml.jackson.databind.JsonMappingException: 无法从 String 中实例化 [简单类型, class java.time.LocalDateTime] 类型的值
com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDateTime] from String
我的 Jax-RS REST API 中有 Java8 LocalDateTime。我的 webapp 部署在 wildfly10 中。当我进行 POST 调用(包括 LocalDateTime 作为参数)时,出现以下异常;
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDateTime] from String value ('2016-06-02T00:08:25.605Z'); no single-String constructor/factory method
at [Source: io.undertow.servlet.spec.ServletInputStreamImpl@396d1714; line: 2, column: 3] (through reference chain: com.leightonobrien.core.model.base.Company["created"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:843)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:277)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1150)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:153)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:144)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:523)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.findDeserializeAndSet(BeanPropertyMap.java:285)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:248)
基于以下指南;
和
和
https://github.com/FasterXML/jackson-datatype-jsr310
我写好了我的provider,在申请路径里注册了;
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
@Provider
public class LocalDateTimeConverterProvider extends JacksonJsonProvider implements ParamConverterProvider {
private final LocalDateTimeConverter converter = new LocalDateTimeConverter();
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (!rawType.equals(LocalDateTime.class))
return null;
return (ParamConverter<T>) converter;
}
public class LocalDateTimeConverter implements ParamConverter<LocalDateTime> {
@Override
public LocalDateTime fromString(String value) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(value, formatter);
return dateTime;
}
@Override
public String toString(LocalDateTime value) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
String formattedDateTime = value.format(formatter);
return formattedDateTime;
}
}
public LocalDateTimeConverterProvider() {
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.registerModule(new JavaTimeModule());
setMapper(mapper);
}
}
import javax.ws.rs.ApplicationPath;
@ApplicationPath("/rest")
public class RestApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>();
set.add(com.test.JsonMoneyProvider.class);
set.add(com.test.DurtaionConverterProvider.class);
set.add(com.test.LocalDateTimeConverterProvider.class);
set.add(com.test.MoneyConverterProvider.class);
...
我叫POST喜欢;
curl -X POST --header 'Content-Type: application/json' -d '{
"created": "2016-06-02T00:08:25.605Z",
"updated": "2016-06-02T00:08:25.605Z",
"id": 0,
"code": "string",
"name": "string",
"abn": "string",
"addresses": [
{
"id": 0,
"address1": "string",
"address2": "string",
"city": "string",
"state": "string",
"postcode": "string",
"country": "string",
"gps": {
"latitude": {
"latitude": 0,
"value": 0
},
"longitude": {
"longitude": 0,
"value": 0
}' 'http://localhost:8080/test2dbwar/rest/Companys'
如何克服上述问题?现在我一无所知..我试图把所有的东西(尽量避免 wildfly 的 jax-rs 复杂支持问题,jackson 序列化问题)并解决问题..
有什么帮助吗?
您链接到的第一个问题涉及 @XxxParam
注释的转换。这就是 ParamConverterProvider
的用途。这是一个与entity body(反)序列化完全不同的(反)序列化过程。
对于实体(反)序列化,使用 MessageBodyReader/MessageBodyWriter
s。 Jackson 在其 JacksonJsonProvider/JacksonJaxbJsonProvider
中提供了一个这样的实现,无论您是否知道,您目前正在使用它。因此 LocalDataTime
的配置需要以某种方式使用该提供程序进行配置。
配置 Jackson 支持 LocalDateTime
序列化的唯一方法是通过它的 ObjectMapper
。您可以创建自定义 Json(De)Serializer
,如前所述 , or you can use the JSR310Module
(that already has custom Json(De)Serializer
for LocalDateTime
), mentioned in 。
要实际配置 JacksonJsonProvider/JacksonJaxbJsonProvider
以使用您配置的 ObjectMapper
,您可以使用 ContextResolver
,如前面两个链接中所述,或者您可以构建 JacksonJsonProvider
与 ObjectMapper
,并注册该提供商
ObjectMapper mapper = new ObjectMapper();
mapper..configurModuleOrSerializer
JacksonJsonProvider provider = new JacksonJsonProvider(mapper);
registerProvier(provider)
个人而言,我会选择 ContextResolver
,如链接中所述。不同之处在于,使用上述代码,ObjectMapper
显式提供给提供者,而使用 ContextResolver
,在运行时,提供者将在 JAX-RS 注册表中搜索 ContextResolver
类型ObjectMapper
,然后通过这种方式获取。
就我而言,添加以下内容对我有用。
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.9</version
</dependency>
并像这样配置 ObjectMapper
:
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
我的 Jax-RS REST API 中有 Java8 LocalDateTime。我的 webapp 部署在 wildfly10 中。当我进行 POST 调用(包括 LocalDateTime 作为参数)时,出现以下异常;
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDateTime] from String value ('2016-06-02T00:08:25.605Z'); no single-String constructor/factory method
at [Source: io.undertow.servlet.spec.ServletInputStreamImpl@396d1714; line: 2, column: 3] (through reference chain: com.leightonobrien.core.model.base.Company["created"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:843)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:277)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1150)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:153)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:144)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:523)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.findDeserializeAndSet(BeanPropertyMap.java:285)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:248)
基于以下指南;
和
和
https://github.com/FasterXML/jackson-datatype-jsr310
我写好了我的provider,在申请路径里注册了;
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
@Provider
public class LocalDateTimeConverterProvider extends JacksonJsonProvider implements ParamConverterProvider {
private final LocalDateTimeConverter converter = new LocalDateTimeConverter();
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (!rawType.equals(LocalDateTime.class))
return null;
return (ParamConverter<T>) converter;
}
public class LocalDateTimeConverter implements ParamConverter<LocalDateTime> {
@Override
public LocalDateTime fromString(String value) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(value, formatter);
return dateTime;
}
@Override
public String toString(LocalDateTime value) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
String formattedDateTime = value.format(formatter);
return formattedDateTime;
}
}
public LocalDateTimeConverterProvider() {
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.registerModule(new JavaTimeModule());
setMapper(mapper);
}
}
import javax.ws.rs.ApplicationPath;
@ApplicationPath("/rest")
public class RestApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>();
set.add(com.test.JsonMoneyProvider.class);
set.add(com.test.DurtaionConverterProvider.class);
set.add(com.test.LocalDateTimeConverterProvider.class);
set.add(com.test.MoneyConverterProvider.class);
...
我叫POST喜欢;
curl -X POST --header 'Content-Type: application/json' -d '{
"created": "2016-06-02T00:08:25.605Z",
"updated": "2016-06-02T00:08:25.605Z",
"id": 0,
"code": "string",
"name": "string",
"abn": "string",
"addresses": [
{
"id": 0,
"address1": "string",
"address2": "string",
"city": "string",
"state": "string",
"postcode": "string",
"country": "string",
"gps": {
"latitude": {
"latitude": 0,
"value": 0
},
"longitude": {
"longitude": 0,
"value": 0
}' 'http://localhost:8080/test2dbwar/rest/Companys'
如何克服上述问题?现在我一无所知..我试图把所有的东西(尽量避免 wildfly 的 jax-rs 复杂支持问题,jackson 序列化问题)并解决问题..
有什么帮助吗?
您链接到的第一个问题涉及 @XxxParam
注释的转换。这就是 ParamConverterProvider
的用途。这是一个与entity body(反)序列化完全不同的(反)序列化过程。
对于实体(反)序列化,使用 MessageBodyReader/MessageBodyWriter
s。 Jackson 在其 JacksonJsonProvider/JacksonJaxbJsonProvider
中提供了一个这样的实现,无论您是否知道,您目前正在使用它。因此 LocalDataTime
的配置需要以某种方式使用该提供程序进行配置。
配置 Jackson 支持 LocalDateTime
序列化的唯一方法是通过它的 ObjectMapper
。您可以创建自定义 Json(De)Serializer
,如前所述 JSR310Module
(that already has custom Json(De)Serializer
for LocalDateTime
), mentioned in
要实际配置 JacksonJsonProvider/JacksonJaxbJsonProvider
以使用您配置的 ObjectMapper
,您可以使用 ContextResolver
,如前面两个链接中所述,或者您可以构建 JacksonJsonProvider
与 ObjectMapper
,并注册该提供商
ObjectMapper mapper = new ObjectMapper();
mapper..configurModuleOrSerializer
JacksonJsonProvider provider = new JacksonJsonProvider(mapper);
registerProvier(provider)
个人而言,我会选择 ContextResolver
,如链接中所述。不同之处在于,使用上述代码,ObjectMapper
显式提供给提供者,而使用 ContextResolver
,在运行时,提供者将在 JAX-RS 注册表中搜索 ContextResolver
类型ObjectMapper
,然后通过这种方式获取。
就我而言,添加以下内容对我有用。
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.9</version
</dependency>
并像这样配置 ObjectMapper
:
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());