Java 8 LocalDate Jackson 格式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28802544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 06:50:19  来源:igfitidea点击:

Java 8 LocalDate Hymanson format

javajsonHymansonjax-rsresteasy

提问by JAB

For java.util.Datewhen I do

对于java.util.Date当我这样做时

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")  
  private Date dateOfBirth;

then in JSON request when I send

然后在我发送时在 JSON 请求中

{ {"dateOfBirth":"01/01/2000"} }  

it works.

有用。

How should I do this for Java 8's LocalDatefield??

我应该如何为Java 8 的 LocalDate字段执行此操作?

I tried having

我试过

@JsonDeserialize(using = LocalDateDeserializer.class)  
@JsonSerialize(using = LocalDateSerializer.class)  
private LocalDate dateOfBirth;  

It didn't work.

它没有用。

Can someone please let me know what's the right way to do this..

有人可以让我知道这样做的正确方法是什么..

Below are dependencies

下面是依赖

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>jaxrs-api</artifactId>
     <version>3.0.9.Final</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.Hymanson.jaxrs</groupId>
    <artifactId>Hymanson-jaxrs-json-provider</artifactId>
    <version>2.4.2</version>
</dependency>
<dependency>
    <groupId>com.wordnik</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>1.3.10</version>
</dependency>

采纳答案by Paul Samsotha

I was never able to get this to work simple using annotations. To get it to work, I created a ContextResolverfor ObjectMapper, then I added the JSR310Module(update: now it is JavaTimeModuleinstead), along with one more caveat, which was the need to set write-date-as-timestamp to false. See more at the documentation for the JSR310 module. Here's an example of what I used.

我从来没有能够使用注释让它简单地工作。为了让它工作,我创建了一个ContextResolverfor ObjectMapper,然后我添加了JSR310Module( update: now it isJavaTimeModule相反),还有一个警告,那就是需要将 write-date-as-timestamp 设置为 false。在 JSR310 模块的文档中查看更多信息。这是我使用的示例。

Dependency

依赖

<dependency>
    <groupId>com.fasterxml.Hymanson.datatype</groupId>
    <artifactId>Hymanson-datatype-jsr310</artifactId>
    <version>2.4.0</version>
</dependency>

Note:One problem I faced with this is that the Hymanson-annotationversion pulled in by another dependency, used version 2.3.2, which cancelled out the 2.4 required by the jsr310. What happened was I got a NoClassDefFound for ObjectIdResolver, which is a 2.4 class. So I just needed to line up the included dependency versions

注意:我遇到的一个问题是Hymanson-annotation另一个依赖项引入的版本使用了 2.3.2 版本,它取消了jsr310. 发生的事情是我得到了一个 NoClassDefFound for ObjectIdResolver,这是一个 2.4 类。所以我只需要排列包含的依赖版本

ContextResolver

上下文解析器

import com.fasterxml.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.databind.SerializationFeature;
import com.fasterxml.Hymanson.datatype.jsr310.JSR310Module;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper MAPPER;

    public ObjectMapperContextResolver() {
        MAPPER = new ObjectMapper();
        // Now you should use JavaTimeModule instead
        MAPPER.registerModule(new JSR310Module());
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return MAPPER;
    }  
}

Resource class

资源类

@Path("person")
public class LocalDateResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getPerson() {
        Person person = new Person();
        person.birthDate = LocalDate.now();
        return Response.ok(person).build();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createPerson(Person person) {
        return Response.ok(
                DateTimeFormatter.ISO_DATE.format(person.birthDate)).build();
    }

    public static class Person {
        public LocalDate birthDate;
    }
}

Test

测试

curl -v http://localhost:8080/api/person
Result:{"birthDate":"2015-03-01"}

curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
Result:2015-03-01

curl -v http://localhost:8080/api/person
结果:{"birthDate":"2015-03-01"}

curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
结果:2015-03-01



See also herefor JAXB solution.

另请参阅此处了解 JAXB 解决方案。

UPDATE

更新

The JSR310Moduleis deprecated as of version 2.7 of Hymanson. Instead, you should register the module JavaTimeModule. It is still the same dependency.

JSR310Module已废弃的Hyman逊的2.7版本。相反,您应该注册模块JavaTimeModule。它仍然是相同的依赖关系。

回答by u5702361

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

works fine for me.

对我来说很好用。

回答by Christopher Yang

@JsonSerialize and @JsonDeserialize worked fine for me. They eliminate the need to import the additional jsr310 module:

@JsonSerialize 和 @JsonDeserialize 对我来说效果很好。它们无需导入额外的 jsr310 模块:

@JsonDeserialize(using = LocalDateDeserializer.class)  
@JsonSerialize(using = LocalDateSerializer.class)  
private LocalDate dateOfBirth;

Deserializer:

解串器:

public class LocalDateDeserializer extends StdDeserializer<LocalDate> {

    private static final long serialVersionUID = 1L;

    protected LocalDateDeserializer() {
        super(LocalDate.class);
    }


    @Override
    public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        return LocalDate.parse(jp.readValueAs(String.class));
    }

}

Serializer:

序列化器:

public class LocalDateSerializer extends StdSerializer<LocalDate> {

    private static final long serialVersionUID = 1L;

    public LocalDateSerializer(){
        super(LocalDate.class);
    }

    @Override
    public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider sp) throws IOException, JsonProcessingException {
        gen.writeString(value.format(DateTimeFormatter.ISO_LOCAL_DATE));
    }
}

回答by Tsolak Barseghyan

In Spring Boot web app, with Hymansonand JSR 310version "2.8.5"

在 Spring Boot Web 应用程序中,使用HymansonJSR 310版本“2.8.5”

compile "com.fasterxml.Hymanson.core:Hymanson-databind:2.8.5"
runtime "com.fasterxml.Hymanson.datatype:Hymanson-datatype-jsr310:2.8.5"

The @JsonFormatworks:

@JsonFormat作品:

import com.fasterxml.Hymanson.annotation.JsonFormat;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthDate;

回答by bdzzaid

Just an update of Christopher answer.

只是克里斯托弗回答的更新。

Since the version 2.6.0

2.6.0版本

<dependency>
    <groupId>com.fasterxml.Hymanson.datatype</groupId>
    <artifactId>Hymanson-datatype-jsr310</artifactId>
    <version>2.9.0</version>
</dependency>

Use the JavaTimeModuleinstead of JSR310Module(deprecated).

使用JavaTimeModule而不是JSR310Module(已弃用)。

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper MAPPER;

    public ObjectMapperContextResolver() {
        MAPPER = new ObjectMapper();
        MAPPER.registerModule(new JavaTimeModule());
        MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return MAPPER;
    }  
}

According to the documentation, the new JavaTimeModule uses same standard settings to default to serialization that does NOT use Timezone Ids, and instead only uses ISO-8601 compliant Timezone offsets.

根据文档,新的 JavaTimeModule 使用相同的标准设置默认为不使用时区 ID 的序列化,而是仅使用符合 ISO-8601 的时区偏移量。

Behavior may be changed using SerializationFeature.WRITE_DATES_WITH_ZONE_ID

可以使用SerializationFeature.WRITE_DATES_WITH_ZONE_ID更改行为

回答by Shadow Man

Since LocalDateSerializerturns it into "[year,month,day]" (a json array) rather than "year-month-day" (a json string) by default, and since I don't want to require any special ObjectMappersetup (you can make LocalDateSerializergenerate strings if you disable SerializationFeature.WRITE_DATES_AS_TIMESTAMPSbut that requires additional setup to your ObjectMapper), I use the following:

由于LocalDateSerializer默认情况下将其转换为“[year,month,day]”(一个 json 数组)而不是“year-month-day”(一个 json 字符串),并且因为我不想需要任何特殊ObjectMapper设置(您可以让LocalDateSerializer如果禁用生成字符串SerializationFeature.WRITE_DATES_AS_TIMESTAMPS但这需要额外的设置你的ObjectMapper),我用的是以下情况:

imports:

进口:

import com.fasterxml.Hymanson.databind.ser.std.ToStringSerializer;
import com.fasterxml.Hymanson.datatype.jsr310.deser.LocalDateDeserializer;

code:

代码:

// generates "yyyy-MM-dd" output
@JsonSerialize(using = ToStringSerializer.class)
// handles "yyyy-MM-dd" input just fine (note: "yyyy-M-d" format will not work)
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate localDate;

And now I can just use new ObjectMapper()to read and write my objects without any special setup.

现在我可以使用它new ObjectMapper()来读取和写入我的对象,而无需任何特殊设置。

回答by Paul Wasilewski

The simplest solution (which supports deserialization and serialization as well) is

最简单的解决方案(也支持反序列化和序列化)是

import com.fasterxml.Hymanson.annotation.JsonFormat;
import com.fasterxml.Hymanson.databind.annotation.JsonDeserialize;
import com.fasterxml.Hymanson.databind.annotation.JsonSerialize;
import com.fasterxml.Hymanson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.Hymanson.datatype.jsr310.ser.LocalDateSerializer;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate dateOfBirth;


While using the following dependencies in your project.

在您的项目中使用以下依赖项时。

Maven

马文

<dependency>
   <groupId>com.fasterxml.Hymanson.core</groupId>
   <artifactId>Hymanson-databind</artifactId>
   <version>2.9.7</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.Hymanson.datatype</groupId>
   <artifactId>Hymanson-datatype-jsr310</artifactId>
   <version>2.9.7</version>
</dependency>

Gradle

摇篮

compile "com.fasterxml.Hymanson.core:Hymanson-databind:2.9.7"
compile "com.fasterxml.Hymanson.datatype:Hymanson-datatype-jsr310:2.9.7"

No additional implementation of a ContextResolver, Serializer or Deserializer is required.

不需要额外的 ContextResolver、Serializer 或 Deserializer 实现。

回答by Pavel

https://stackoverflow.com/a/53251526/1282532is the simplest way to serialize/deserialize property. I have two concerns regarding this approach - up to some point violation of DRY principle and high coupling between pojo and mapper.

https://stackoverflow.com/a/53251526/1282532是序列化/反序列化属性的最简单方法。我对这种方法有两个担忧——在某种程度上违反了 DRY 原则以及 pojo 和 mapper 之间的高耦合。

public class Trade {
    @JsonFormat(pattern = "yyyyMMdd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate tradeDate;
    @JsonFormat(pattern = "yyyyMMdd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate maturityDate;
    @JsonFormat(pattern = "yyyyMMdd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate entryDate;
}

In case you have POJO with multiple LocalDate fields it's better to configure mapper instead of POJO. It can be as simple as https://stackoverflow.com/a/35062824/1282532if you are using ISO-8601 values ("2019-01-31")

如果您的 POJO 具有多个 LocalDate 字段,最好配置映射器而不是 POJO。如果您使用的是 ISO-8601 值(“2019-01-31”),它可以像https://stackoverflow.com/a/35062824/1282532一样简单

In case you need to handle custom format the code will be like this:

如果您需要处理自定义格式,代码将如下所示:

ObjectMapper mapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyyMMdd")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyyMMdd")));
mapper.registerModule(javaTimeModule);

The logic is written just once, it can be reused for multiple POJO

逻辑只写一次,可以复用多个POJO

回答by nanosoft

In configuration class define LocalDateSerializerand LocalDateDeserializerclass and register them to ObjectMappervia JavaTimeModulelike below:

在配置类中定义LocalDateSerializerLocalDateDeserializer类,并通过JavaTimeModule将它们注册到ObjectMapper,如下所示:

@Configuration
public class AppConfig
{
@Bean
    public ObjectMapper objectMapper()
    {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_EMPTY);
        //other mapper configs
        // Customize de-serialization


        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
        mapper.registerModule(javaTimeModule);

        return mapper;
    }

    public class LocalDateSerializer extends JsonSerializer<LocalDate> {
        @Override
        public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(value.format(Constant.DATE_TIME_FORMATTER));
        }
    }

    public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {

        @Override
        public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            return LocalDate.parse(p.getValueAsString(), Constant.DATE_TIME_FORMATTER);
        }
    }
}

回答by KayV

The following annotation worked fine for me.

以下注释对我来说效果很好。

No extra dependencies needed.

不需要额外的依赖。

    @JsonProperty("created_at")
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    private LocalDateTime createdAt;