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
Java 8 LocalDate Hymanson format
提问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 ContextResolver
for ObjectMapper
, then I added the JSR310Module
(update: now it is JavaTimeModule
instead), 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.
我从来没有能够使用注释让它简单地工作。为了让它工作,我创建了一个ContextResolver
for 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-annotation
version 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 JSR310Module
is 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 应用程序中,使用Hymanson和JSR 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 @JsonFormat
works:
该@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 LocalDateSerializer
turns 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 ObjectMapper
setup (you can make LocalDateSerializer
generate strings if you disable SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
but 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:
在配置类中定义LocalDateSerializer和LocalDateDeserializer类,并通过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;