Jersey 解析 Java 8 日期时间
这是我的用户类,我将符合 ISO 标准的日期时间保存在我的数据库中.
This is my user class, and I to save ISO compliant date time in my database.
public class User {
@Id
private String id;
private String email;
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime loginDate;
}
这是我的泽西控制器:
@POST
@Consumes("application/json")
@Produces("application/json")
public Response create( User user) {
Map<Object, Object> apiResponse = new HashMap<Object, Object>();
Map<Object, Object> response = new HashMap<Object, Object>();
user = (User) userService.create(user);
}
我怎样才能在球衣中使用像这样的日期时间格式?是否可以发送数据时间 String
并自动创建 Java 8 日期时间对象?
How can can I consume a datetime format like this one in jersey? Is it possible to send a datatime String
and create Java 8 date time object automatically?
{
"email" : "imz.mrz@gmail.com"
"loginDate" : "2015-04-17T06:06:51.465Z"
}
#
更新:
我使用的是 Spring boot jersey,并且有其他 jsr 包
I was using Spring boot jersey, and had other jsr packages
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
所以我删除了除了 spring-boot-jersey 包之外的所有包.将此注释用于 LocalDateTime
So I removed all the packages except from spring-boot-jersey package. use this annotation for LocalDateTime
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
这样我可以使用 ISODate 并将 ISODate() 保存到 mongodb 并生成完整格式的 mongodb LocalDateTime 到前端.
This way I can consume ISODate and save ISODate() to mongodb and produce full formated mongodb LocalDateTime to frontend.
问题解决了.
推荐答案
我看到的几个选项...
选项 1:
假设您有 JAXB 注释支持,Jackson 作为 JSON 提供者...
Couple options I see...
Option 1:
Assuming you have JAXB annotation support with Jackson as the JSON provider...
您可以使用 XmlAdapter
.例如
public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
@Override
public LocalDateTime unmarshal(String dateString) throws Exception {
Instant instant = Instant.parse(dateString);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return dateTime;
}
@Override
public String marshal(LocalDateTime dateTime) throws Exception {
Instant instant = dateTime.toInstant(ZoneOffset.UTC);
return DateTimeFormatter.ISO_INSTANT.format(instant);
}
}
参见 Instant API 了解更多信息.
See the Instant API for more information.
然后你可以用适配器注释字段/属性
Then you can just annotate the field/property with the adapter
@XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
private LocalDateTime loginDate;
你也可以在包级别声明注解,这样包中的所有使用都将使用适配器,而无需注解.您可以在包内的名为 package-info.java
的文件中执行此操作
You could also declare the annotation at the package level, so that all uses in the package will use the adapter, without the need to annotate. You do so in a file named package-info.java
put inside the package
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(type = LocalDateTime.class,
value = LocalDateTimeAdapter.class)
})
package thepackage.of.the.models;
import java.time.LocalDateTime;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
选项 2:
直接使用 Jackson API.意思是,使用 JsonDeserializer
和 JsonSerializer
.例如
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jp,
DeserializationContext dc) throws IOException, JsonProcessingException {
ObjectCodec codec = jp.getCodec();
TextNode node = (TextNode)codec.readTree(jp);
String dateString = node.textValue();
Instant instant = Instant.parse(dateString);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return dateTime;
}
}
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime dateTime, JsonGenerator jg,
SerializerProvider sp) throws IOException, JsonProcessingException {
Instant instant = dateTime.toInstant(ZoneOffset.UTC);
jg.writeString(DateTimeFormatter.ISO_INSTANT.format(instant));
}
}
您可以在字段/属性级别应用此功能
You can apply this at the field/property level
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime loginDate;
或者在ObjectMapper
级别(所以你不需要到处注释)
Or at the ObjectMapper
level (so you don't need to annotate everywhere)
@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper = new ObjectMapper();
public ObjectMapperContextResolver() {
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
mapper.registerModule(module);
// add JAXB annotation support if required
mapper.registerModule(new JaxbAnnotationModule());
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
基本上发生的情况是,用于 ummarshalling/marshalling 的 MessageBodyWriter
/MessageBodyReader
将调用 getContext
方法来获取 ObjectMapper
Basically what happens, is that the MessageBodyWriter
/MessageBodyReader
used for ummarshalling/marshalling, will call the getContext
method to get the ObjectMapper
注意:
上述解决方案将从
2007-12-03T10:15:30.00Z
格式解析,如Instant.parse
,并将序列化为相同的格式,如DateTimeFormatter.ISO_INSTANT
The above solutions will parse from the format
2007-12-03T10:15:30.00Z
, as documented inInstant.parse
, and will serialize to the same format, as documented inDateTimeFormatter.ISO_INSTANT
以上内容还假设您使用 Jackson 作为序列化器.我使用以下依赖项(使用 Jersey 2.16)进行测试
The above is also assuming you are using Jackson as the Serializer. I used the below dependency (with Jersey 2.16) to test
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.16</version>
</dependency>
依赖项使用 JacksonJaxbJsonProvider
来支持 JAXB 注释.如果您使用的是 1.x 等较低版本的 Jersey,如果您启用 POJO 映射功能,则 jersey-json
依赖项应提供 JAXB 注释支持.或者对于 Jersey 1.x,如果你想使用 Jackson 2,你可以使用这个依赖
The dependency uses a JacksonJaxbJsonProvider
for JAXB annotation support. If you are using a lower version of Jersey like 1.x, the jersey-json
dependency should offer JAXB annotation support, if you enable the POJO mapping feature. Alternatively for Jersey 1.x, if you want to use Jackson 2, you can use this dependency
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
这实际上是 jersey-media-json-jackson
使用的.因此,您可以显式注册 JacksonJaxbJsonProvider
,或添加 Jackson 包 (com.fasterxml.jackson.jaxrs.json
) 以列出要扫描的包
which is actually what is used by jersey-media-json-jackson
. So you could explicitly register the JacksonJaxbJsonProvider
, or add the Jackson package (com.fasterxml.jackson.jaxrs.json
) to list packages to scan
另见:
- Java 8 LocalDate Jackson 格式.Jackson 模块已经为 Java 8 日期/时间 API 提供了序列化程序.
- Java 8 LocalDate Jackson format. There is Jackson Module that already comes with serializers for the Java 8 date/time APIs.
相关文章