GVKun编程网logo

Jackson使用Java 8将Elasticsearch反序列化为LocalDateTime(jackson list map 反序列化)

14

对于Jackson使用Java8将Elasticsearch反序列化为LocalDateTime感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍jacksonlistmap反序列化,并为您提供关

对于Jackson使用Java 8将Elasticsearch反序列化为LocalDateTime感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍jackson list map 反序列化,并为您提供关于fastjson反序列化LocalDateTime失败的问题java.time.format.DateTimeParseException: Text ''2019-05-24 13:52...、jackson全局配置解析localDateTime、Jackson和java.sql.Time序列化/反序列化、Java 8 date/time type `java.time.LocalDateTime` not supported by default:日期序列化问题的有用信息。

本文目录一览:

Jackson使用Java 8将Elasticsearch反序列化为LocalDateTime(jackson list map 反序列化)

Jackson使用Java 8将Elasticsearch反序列化为LocalDateTime(jackson list map 反序列化)

如何解决Jackson使用Java 8将Elasticsearch反序列化为LocalDateTime?

要从LocalDateTime纪元的毫秒数开始构建,1970-01-01T00:00:00Z我们需要一个时区。在2.9.9版中,当出现毫秒时,它将引发异常:

不允许使用原始时间戳(1563448935000)java.time.LocalDateTime:需要其他信息,例如偏移量或时区(请参阅类Javadocs)

但是我们可以实现我们的反序列化程序,它将尝试使用默认时区进行此操作。示例实现如下所示:

class MillisOrLocalDateTimeDeserializer extends LocalDateTimeDeserializer {

    public MillisOrLocalDateTimeDeserializer() {
        super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }

    @Override
    public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
            long value = parser.getValueAsLong();
            Instant instant = Instant.ofEpochMilli(value);

            return LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
        }

        return super.deserialize(parser, context);
    }

}

ZoneOffset.UTC用来。您可以根据自己的意愿提供或使用系统默认值。用法示例:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // override default
        javaTimeModule.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer());

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(javaTimeModule);

        String json = "{\"created\":1563448935000}";
        System.out.println(mapper.readValue(json, Created.class));

    }
}

class Created {

    private LocalDateTime created;

    // getters, setters, toString
}

上面的代码打印:

Created{created=2019-07-18T11:22:15}

编辑:使用Jackson 2.9.0,由于这个问题,提供的代码将不会被调用,因为findAndRegisterModules在注册自定义模块后,它将被覆盖。删除该呼叫将使整个方案起作用。如果以上方法不适用于您的版本,则需要调试默认实现并查找原因。

解决方法

我们在日期字段中填充了longinlasticsearch索引。

字段映射为:

@Field(type = FieldType.Date)
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
private LocalDateTime created;

我使用Jackson JavaTimeModuleJdk8Module使用以下配置:

@Bean
public ElasticsearchOperations elasticsearchTemplate() {
   return new ElasticsearchRestTemplate(client(),new CustomEntityMapper());
}

public static class CustomEntityMapper implements EntityMapper {

        private final ObjectMapper objectMapper;

        public CustomEntityMapper() {
            //we use this so that Elasticsearch understands LocalDate and LocalDateTime objects
            objectMapper = new ObjectMapper()
                              .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false)
                              .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true)
                              .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,false)
                              .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false)
                              .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS,false)
                              //MUST be registered BEFORE calling findAndRegisterModules
                              .registerModule(new JavaTimeModule())
                              .registerModule(new Jdk8Module());
            //only autodetect fields and ignore getters and setters for nonexistent fields when serializing/deserializing
            objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
                            .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                            .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                            .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                            .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
            //load the other available modules as well
            objectMapper.findAndRegisterModules();
        }

        @Override
        public String mapToString(Object object) throws IOException {
            return objectMapper.writeValueAsString(object);
        }

        @Override
        public <T> T mapToObject(String source,Class<T> clazz) throws IOException {
            return objectMapper.readValue(source,clazz);
        }
}

但是,当我尝试使用以下字段解析索引中的实体时:

"created" : 1563448935000

我收到一个错误:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_NUMBER_INT),expected VALUE_STRING: Expected array or string.

我认为,可以对long日期反序列化,但是我看不到缺少的内容。

如果我将其映射到Long它,则当然可以工作,并且如果将值存储为String,我们也可以将其成形并正确格式化@JsonFormat。但是有可能也有long->LocalDateTime吗?

fastjson反序列化LocalDateTime失败的问题java.time.format.DateTimeParseException: Text ''2019-05-24 13:52...

fastjson反序列化LocalDateTime失败的问题java.time.format.DateTimeParseException: Text ''2019-05-24 13:52...

<div id="cnblogs_post_body"><p>本地java类</p> <div><div><span><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div> <pre><span>import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;

</span><span>/*</span><span>**

  • 问题处理记录 </span><span>*/</span> <span>public</span> <span>class</span><span> UserIssueProcessDto {

    </span><span>/*</span><span>**

    • 处理说明 </span><span>/</span> <span>private</span><span> String f_clsm; </span><span>/</span><span>**
    • 施工队处理反馈 </span><span>*/</span> <span>private</span><span> String f_fk;

    </span><span>/*</span><span>**

    • 处理开始时间 </span><span>*/</span><span> @DateTimeFormat( pattern </span>= <span>"</span><span>yyyy-MM-dd HH:mm:ss</span><span>"</span><span>) </span><span>private</span><span> LocalDateTime f_clkssj;

    </span><span>/*</span><span>**

    • 处理结束时间 </span><span>*/</span><span> @DateTimeFormat( pattern </span>= <span>"</span><span>yyyy-MM-dd HH:mm:ss</span><span>"</span><span>) </span><span>private</span><span> LocalDateTime f_cljssj;

    </span><span>/*</span><span>**

    • 处理时长 </span><span>*/</span> <span>private</span><span> Double duration;

    </span><span>private</span><span> String f_clry;

    </span><span>private</span><span> String f_clryid;

    </span><span>/*</span><span>**

    • 填写人ID </span><span>/</span> <span>private</span><span> Integer creatorId; </span><span>/</span><span>**
    • 填写人名称 </span><span>*/</span> <span>private</span><span> String creatorName;

    </span><span>/*</span><span>**

    • 添加时间 </span><span>*/</span> <span>private</span><span> LocalDateTime f_addtime;

    </span><span>public</span><span> String getF_clsm() { </span><span>return</span><span> f_clsm; }

    </span><span>public</span> <span>void</span><span> setF_clsm(String f_clsm) { </span><span>this</span>.f_clsm =<span> f_clsm; }

    </span><span>public</span><span> String getF_fk() { </span><span>return</span><span> f_fk; }

    </span><span>public</span> <span>void</span><span> setF_fk(String f_fk) { </span><span>this</span>.f_fk =<span> f_fk; }

    </span><span>public</span><span> LocalDateTime getF_clkssj() { </span><span>return</span><span> f_clkssj; }

    </span><span>public</span> <span>void</span><span> setF_clkssj(LocalDateTime f_clkssj) { </span><span>this</span>.f_clkssj =<span> f_clkssj; }

    </span><span>public</span><span> LocalDateTime getF_cljssj() { </span><span>return</span><span> f_cljssj; }

    </span><span>public</span> <span>void</span><span> setF_cljssj(LocalDateTime f_cljssj) { </span><span>this</span>.f_cljssj =<span> f_cljssj; }

    </span><span>public</span><span> Double getDuration() { </span><span>return</span><span> duration; }

    </span><span>public</span> <span>void</span><span> setDuration(Double duration) { </span><span>this</span>.duration =<span> duration; }

    </span><span>public</span><span> String getF_clry() { </span><span>return</span><span> f_clry; }

    </span><span>public</span> <span>void</span><span> setF_clry(String f_clry) { </span><span>this</span>.f_clry =<span> f_clry; }

    </span><span>public</span><span> String getF_clryid() { </span><span>return</span><span> f_clryid; }

    </span><span>public</span> <span>void</span><span> setF_clryid(String f_clryid) { </span><span>this</span>.f_clryid =<span> f_clryid; }

    </span><span>public</span><span> Integer getCreatorId() { </span><span>return</span><span> creatorId; }

    </span><span>public</span> <span>void</span><span> setCreatorId(Integer creatorId) { </span><span>this</span>.creatorId =<span> creatorId; }

    </span><span>public</span><span> String getCreatorName() { </span><span>return</span><span> creatorName; }

    </span><span>public</span> <span>void</span><span> setCreatorName(String creatorName) { </span><span>this</span>.creatorName =<span> creatorName; }

    </span><span>public</span><span> LocalDateTime getF_addtime() { </span><span>return</span><span> f_addtime; }

    </span><span>public</span> <span>void</span><span> setF_addtime(LocalDateTime f_addtime) { </span><span>this</span>.f_addtime =<span> f_addtime; } }</span></pre>

<div><span><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div> <p>测试代码</p> <div> <pre>String json = "[{\"f_clsm\":\"111\",\"f_fk\":\"-1\",\"f_clkssj\":\"2019-05-24 13:52:11\",\"f_cljssj\":\"2019-05-24 14:52:11\",\"f_clryid\":\"1000645\"}]"<span>;

    List</span>&lt;UserIssueProcessDto&gt; list = JSON.parseObject(json, <span>new</span> TypeReference&lt;List&lt;UserIssueProcessDto&gt;&gt;<span>() {});
    System.out.println(list);</span></pre>

</div> <p>最初发现项目中使用的是fastjson-1.2.7.jar</p> <p>报错如下:</p> <p>com.alibaba.fastjson.JSONException: Text ''2019-05-24 13:52:11'' could not be parsed at index 10</p> <p> at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:555)<br> at com.alibaba.fastjson.JSON.parseObject(JSON.java:251)<br> at com.alibaba.fastjson.JSON.parseObject(JSON.java:227)<br> at com.alibaba.fastjson.JSON.parseObject(JSON.java:181)<br> at com.TestSpringMVCConvert.test(TestSpringMVCConvert.java:19)<br> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)<br> at java.lang.reflect.Method.invoke(Method.java:498)<br> at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)<br> at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)<br> at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)<br> at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)<br> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)<br> at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)<br> at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)<br> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)<br> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)<br> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)<br> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)<br> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)<br> at org.junit.runners.ParentRunner.run(ParentRunner.java:300)<br> at org.junit.runner.JUnitCore.run(JUnitCore.java:157)<br> at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)<br> at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)<br> at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)<br> at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)<br>Caused by: java.time.format.DateTimeParseException: Text ''2019-05-24 13:52:11'' could not be parsed at index 10<br> at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)<br> at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)<br> at java.time.LocalDateTime.parse(LocalDateTime.java:492)<br> at java.time.LocalDateTime.parse(LocalDateTime.java:477)<br> at com.alibaba.fastjson.parser.deserializer.Jdk8DateCodec.deserialze(Jdk8DateCodec.java:35)<br> at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField(DefaultFieldDeserializer.java:33)<br> at com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer.parseField(ASMJavaBeanDeserializer.java:74)<br> at com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer$InnerJavaBeanDeserializer.parseField(ASMJavaBeanDeserializer.java:86)<br> at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:330)<br> at com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer.parseRest(ASMJavaBeanDeserializer.java:100)<br> at Fastjson_ASM_UserIssueProcessDto_1.deserialze(Unknown Source)<br> at com.alibaba.fastjson.parser.DefaultJSONParser.parseArray(DefaultJSONParser.java:635)<br> at com.alibaba.fastjson.parser.deserializer.CollectionDeserializer.deserialze(CollectionDeserializer.java:63)<br> at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:551)<br> ... 26 more</p> <p>最早发现这个问题是在springmvc实体属性注入的时候,经过修改各种springmvc配置无效。</p> <p>后来联想到最近使用的mybatis使用LocalDateTime/LocalDate等类使用了jsr310的时间类,需要额外添加jar包支持。</p> <p>最初错误的把jackson-datatype-jsr310-2.7.0-rc1.jar添加进来,调试一直无效。</p> <p>后来发现一篇文章<span><strong><a href="https://www.oschina.net/question/2258299_2176231" target="_blank"><span>Fastjson支持Java8中的LocalDateTime吗?</span></a>,</strong></span>说fastjson-1.2.11支持,开始更换版本。</p> <p>笔者从<strong><span>mvnrepository.com</span></strong>下载相应的版本,经过最终测试,<ahref="https://my.oschina.net/wenshao" target="_blank">wenshao</a>的说法是错误的。</p> <p><strong><span>必须使用fastjson-1.2.12版本以上才能正常解析。</span></strong></p> <p>原文地址:https://www.cnblogs.com/passedbylove/p/10930665.html</p></div>

jackson全局配置解析localDateTime

jackson全局配置解析localDateTime

  • 相信很多前端对接后段时间类型转换的问题,时间格式不一致的问题,通过jackson也可以做到全局的配置,不在使用注解单个判断时间类型
引入的maven  
<dependency>
 <groupId>cn.hutool</groupId>
 <artifactId>hutool-all</artifactId>
 <hutools.version>5.5.1</hutools.version>
</dependency>
///配置自定义model
public class LocalJavaTimeModule extends SimpleModule {

public CustomJavaTimeModule() {
super(PackageVersion.VERSION);
this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(
DatePattern.NORM_DATETIME_PATTERN)));
this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));

}
@Configuration
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {

@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
/**
* 配置Date的格式化
*/
builder.locale(Locale.CHINA);
builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
/**
* 配置java8 时间配置
*/
builder.modules(new LocalJavaTimeModule());
};
}
}

这样就可以了,当然多模块可以做成一个插件starter之类的

Jackson和java.sql.Time序列化/反序列化

Jackson和java.sql.Time序列化/反序列化

如何解决Jackson和java.sql.Time序列化/反序列化?

解决方案是使用您自己的解串器:

import java.io.IOException;
import java.sql.Time;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

public class sqlTimeDeserializer extends JsonDeserializer<Time> {

    @Override
    public Time deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        return Time.valueOf(jp.getValueAsstring() + ":00");
    }
}

然后在实体中:

@JsonFormat(pattern = "HH:mm")
@JsonDeserialize(using = sqlTimeDeserializer.class)
@Column(name = "start_time")
private Time                startTime;

解决方法

Hibernate受管实体中考虑以下属性:

@JsonFormat(pattern = "HH:mm")
@Column(name = "start_time")
private java.sql.Time startTime;

我向Spring Controller
发布了一个JSON-object对象,@RequestBodyJackson对象应该映射到实体(pojo)的实例中。

Jackson显然无法将时间字符串反序列化为 java.sql.Time,因为我收到了以下异常:

.w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException:
Could not read document: Can not construct instance of java.sql.Time,problem: null

如何指导我Jackson理解该怎么办?

Java 8 date/time type `java.time.LocalDateTime` not supported by default:日期序列化问题

Java 8 date/time type `java.time.LocalDateTime` not supported by default:日期序列化问题

Java 8 date/time type `java.time.LocalDateTime` not supported by default:日期序列化问题

jackson默认不支持java8 LocalDateTime的序列化和反序列化,那控制台也显示了解决的办法,只不过并不全。

解决办法一:将实体类中的LocalDateTime转为Date类型

解决办法二:

<dependency>
	<groupId>com.fasterxml.jackson.datatype</groupId>
	<artifactId>jackson-datatype-jsr310</artifactId>
	<version>2.13.0</version>
</dependency>

通过注解指定

@TableField("update_time")
    @ApiModelProperty("更新时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //此注解用来接收字符串类型的参数封装成LocalDateTime类型
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8", shape = JsonFormat.Shape.STRING) //此注解将date类型数据转成字符串响应出去
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)		// 反序列化
    @JsonSerialize(using = LocalDateTimeSerializer.class)		// 序列化
    private LocalDateTime updateTime;
    @TableField("create_time")
    @ApiModelProperty("添加时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") //此注解用来接收字符串类型的参数封装成LocalDateTime类型
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8", shape = JsonFormat.Shape.STRING) //此注解将date类型数据转成字符串响应出去
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)		// 反序列化
    @JsonSerialize(using = LocalDateTimeSerializer.class)		// 序列化
    private LocalDateTime createTime;

 

配置全局

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
        messageConverter.setObjectMapper(objectMapper);
        converters.add(0, messageConverter);
    }
}

解决办法三:

用阿里的FastJson替换ObjectMapper

 

 

 

关于Jackson使用Java 8将Elasticsearch反序列化为LocalDateTimejackson list map 反序列化的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于fastjson反序列化LocalDateTime失败的问题java.time.format.DateTimeParseException: Text ''2019-05-24 13:52...、jackson全局配置解析localDateTime、Jackson和java.sql.Time序列化/反序列化、Java 8 date/time type `java.time.LocalDateTime` not supported by default:日期序列化问题等相关内容,可以在本站寻找。

本文标签: