出现错误信息:org.codehaus.jackson.map.JsonMappingException: 无法从JSON字符串实例化类型为[简单类型,类java.time.LocalDateTime]的值;没有单一字符串构造函数/工厂方法(通过引用链:MyDTO["field1"]->SubDTO["date"])
数据类型模块,使Jackson识别Java 8日期和时间API数据类型(JSR-310)。
registerModule(new JSR310Module())
或 findAndRegisterModules()
。请参见https://github.com/FasterXML/jackson-datatype-jsr310,如果您使用Spring框架,则以下是如何自定义映射器对象的方法:https://dev59.com/Omsz5IYBdhLWcg3wg4Cv。 - Alexander TaylorOffsetDateTime
,但无法运行。@Test
public void testJacksonOffsetDateTimeDeserializer() throws IOException {
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
String json = "\"2015-10-20T11:00:00-8:30\"";
mapper.readValue(json, OffsetDateTime.class);
}
- Abhijit Sarkarjackson-datatype-jsr310
,你需要在对象映射器中注册 JavaTimeModule
,即 objectMapper.registerModule(new JavaTimeModule());
,在序列化和反序列化时都要注册。 - GrandAdmiral如果您正在使用 fasterxml 的 ObjectMapper 类,那么默认情况下 ObjectMapper 不会理解 LocalDateTime 类,因此您需要在 gradle/maven 中添加另一个依赖项:
如果您正在使用 fasterxml 的 ObjectMapper 类,那么默认情况下 ObjectMapper 不会理解 LocalDateTime 类,因此您需要在 gradle/maven 中添加另一个依赖项:
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.3'
现在您需要将该库提供的数据类型支持注册到对象映射器对象中,方法如下:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
现在,在你的jsonString中,你可以像下面这样轻松地放入你的java.LocalDateTime字段:
{
"user_id": 1,
"score": 9,
"date_time": "2016-05-28T17:39:44.937"
}
通过这样做,您的 Json 文件转换为 Java 对象将正常工作,您可以按照以下步骤读取文件:
objectMapper.readValue(jsonString, new TypeReference<List<User>>() {
});
ObjectMapper
时,findAndRegisterModules()
是我所缺少的关键部分。 - Xaero DegreazobjectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- Janetmapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
- CᴴᴀZ更新:出于历史原因,保留此答案,但我不建议使用。请参见上面接受的答案。
告诉Jackson使用您自定义的[反]序列化类进行映射:
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime ignoreUntil;
提供自定义类:
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException {
arg1.writeString(arg0.toString());
}
}
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser arg0, DeserializationContext arg1) throws IOException {
return LocalDateTime.parse(arg0.getText());
}
}
随机事实:如果我嵌套上述类并且不将它们设为静态,错误消息就会很奇怪:org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
这个 Maven 依赖项将解决你的问题:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.4</version>
</dependency>
有一件事情困扰了我,那就是在反序列化过程中,ZonedDateTime的时区被更改为GMT。 事实证明,Jackson默认会用上下文环境中的一个时区替换它。 若要保留原来的时区,必须禁用此“功能”。
Jackson2ObjectMapperBuilder.json()
.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE
之外,我还必须禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
。 - Matt Watson所有您需要知道的都在Jackson文档中。 https://www.baeldung.com/jackson-serialize-dates
Ad.9迅速为我解决了问题。
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
jackson-datatype-jsr310
依赖项是不够的,你提到的三行代码解决了我的问题。感谢您发布参考资料。 - Francisco Acevedo当我使用Spring Boot时,我遇到了类似的问题。 在使用Spring Boot 1.5.1.RELEASE时,我所需要做的就是添加依赖项:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
在较新版本的Jackson JSR中,例如registerModule(new JSR310Module())
已被弃用,现在建议使用的是JavaTimeModule
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonFactory {
private static ObjectMapper objectMapper = null;
public static ObjectMapper getObjectMapper() {
if (objectMapper == null) {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
}
return objectMapper;
}
}
如果由于任何原因无法使用jackson-modules-java8
,则可以使用@JsonIgnore
、@JsonGetter
和@JsonSetter
将即时字段序列化为long
:
public class MyBean {
private Instant time = Instant.now();
@JsonIgnore
public Instant getTime() {
return this.time;
}
public void setTime(Instant time) {
this.time = time;
}
@JsonGetter
private long getEpochTime() {
return this.time.toEpochMilli();
}
@JsonSetter
private void setEpochTime(long time) {
this.time = Instant.ofEpochMilli(time);
}
}
例子:
@Test
public void testJsonTime() throws Exception {
String json = new ObjectMapper().writeValueAsString(new MyBean());
System.out.println(json);
MyBean myBean = new ObjectMapper().readValue(json, MyBean.class);
System.out.println(myBean.getTime());
}
产量{"epochTime":1506432517242}
2017-09-26T13:28:37.242Z
timezone
信息? - CᴴᴀZjava.time.Instant
has no time zone - it's "An instantaneous point on the time-line."
If you want to (de-)serialize TimeZone
however you can do it in the same way as above by simply serializing TimeZone.getID()
(annotated as @JsonGetter
). For deserialization you can use TimeZone.getTimeZone(timeZoneId)
(annotated as @JsonSetter
). The methods get/setTimeZone()
are - again - annotated as @JsonIgnore
- Udo如果你正在使用Jersey,那么你需要像其他人建议的那样添加Maven依赖项(jackson-datatype-jsr310),并像下面这样注册你的对象映射器实例:
@Provider
public class JacksonObjectMapper implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public JacksonObjectMapper() {
defaultObjectMapper = createDefaultMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
private static ObjectMapper createDefaultMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
在注册Jackson资源时,您需要像这样添加此映射器:
final ResourceConfig rc = new ResourceConfig().packages("<your package>");
rc
.register(JacksonObjectMapper.class)
.register(JacksonJaxbJsonProvider.class);
如果您正在使用Jackson序列化器,那么以下是使用日期模块的方法:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.apache.kafka.common.serialization.Serializer;
public class JacksonSerializer<T> implements Serializer<T> {
private final ObjectMapper mapper = new ObjectMapper()
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
@Override
public byte[] serialize(String s, T object) {
try {
return mapper.writeValueAsBytes(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
e.printStackTrace()
的代码片段不应该被发布。只需捕获异常并抛出即可。 - Dariusz