我看到的几种选择...
选项1:
假设您使用Jackson作为JSON提供程序,并具有JAXB注释支持...
您可以使用一个 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。
然后,您只需使用适配器对该字段/属性进行注释即可。
@XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
private LocalDateTime loginDate
您还可以在包级别上声明注解,这样包中的所有使用都将使用适配器,无需进行注释。 在名为package-info.java
的文件中放置该注解即可。
@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));
}
}
您可以在字段/属性级别应用此项。
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime loginDate;
或者在ObjectMapper
级别进行操作(这样你就不需要在每个地方添加注释)
@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);
mapper.registerModule(new JaxbAnnotationModule());
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
基本上发生的事情是,用于反序列化/序列化的MessageBodyWriter/MessageBodyReader将调用getContext方法以获取ObjectMapper。
注意:
- 上述解决方案将从格式2007-12-03T10:15:30.00Z进行解析,如
Instant.parse
中所述,并将序列化为相同的格式,如
DateTimeFormatter.ISO_INSTANT
中所述。
- 上述假定您正在使用Jackson作为序列化程序。我使用了以下依赖项(与Jersey 2.16一起)进行测试。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.16</version>
</dependency>
该依赖项使用 JacksonJaxbJsonProvider
以支持 JAXB 注解。如果你使用的是较低版本的 Jersey,例如 1.x,则 jersey-json
依赖应该提供了 JAXB 注解支持,如果你启用了 POJO 映射功能。或者对于 Jersey 1.x,如果你想要使用 Jackson 2,可以使用这个依赖项。
<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
) 添加到要扫描的包列表中。
更新
另请参见: