泽西岛 + Jackson JSON 日期格式序列化 - 如何更改格式或使用自定义 JacksonJsonProvider
我正在使用 Jersey + Jackson 为我的应用程序提供 REST JSON 服务层。我遇到的问题是默认的日期序列化格式如下所示:
"CreationDate":1292236718456
起初我以为它是 UNIX 时间戳...但它太长了。我的客户端 JS 库在反序列化这种格式时遇到问题(它支持一堆不同的日期格式,但我想不支持这个)。我想更改格式,以便我的库可以使用它(例如 ISO)。我该怎么做...我找到了一段可以提供帮助的代码,但是...我应该把它放在哪里,因为我不控制杰克逊序列化器实例化(泽西岛控制)?
objectMapper.configure(
SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
我还找到了自定义 JacksonJsonProvider
的代码 - 问题是..如何让我的所有 POJO 类都使用它?
@Provider
public class MessageBodyWriterJSON extends JacksonJsonProvider {
private static final String DF = "yyyy-MM-dd’T'HH:mm:ss.SSSZ";
@Override
public boolean isWriteable(Class arg0, Type arg1, Annotation[] arg2,
MediaType arg3) {
return super.isWriteable(arg0, arg1, arg2,
arg3);
}
@Override
public void writeTo(Object target, Class arg1, Type arg2, Annotation[] arg3,
MediaType arg4, MultivaluedMap arg5, OutputStream outputStream)
throws IOException, WebApplicationException {
SimpleDateFormat sdf=new SimpleDateFormat(DF);
ObjectMapper om = new ObjectMapper();
om.getDeserializationConfig().setDateFormat(sdf);
om.getSerializationConfig().setDateFormat(sdf);
try {
om.writeValue(outputStream, target);
} catch (JsonGenerationException e) {
throw e;
} catch (JsonMappingException e) {
throw e;
} catch (IOException e) {
throw e;
}
}
}
I am using Jersey + Jackson to provide REST JSON services layer for my application. The problem I have is that the default Date serialization format looks like that:
"CreationDate":1292236718456
At first I thought it is a UNIX timestamp... but it is too long for that. My client-side JS library has problems deserializing this format (it supports a bunch of different date formats but not this one I suppose). I want to change the format so that it can be consumable by my library (to ISO for example). How do I do that... I found a piece of code that could help but... where do I put it as I don't control the Jackson serializer instantiation (Jersey does)?
objectMapper.configure(
SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
I also found this code for custom JacksonJsonProvider
- the question is .. how do I make all my POJO classes use it?
@Provider
public class MessageBodyWriterJSON extends JacksonJsonProvider {
private static final String DF = "yyyy-MM-dd’T'HH:mm:ss.SSSZ";
@Override
public boolean isWriteable(Class arg0, Type arg1, Annotation[] arg2,
MediaType arg3) {
return super.isWriteable(arg0, arg1, arg2,
arg3);
}
@Override
public void writeTo(Object target, Class arg1, Type arg2, Annotation[] arg3,
MediaType arg4, MultivaluedMap arg5, OutputStream outputStream)
throws IOException, WebApplicationException {
SimpleDateFormat sdf=new SimpleDateFormat(DF);
ObjectMapper om = new ObjectMapper();
om.getDeserializationConfig().setDateFormat(sdf);
om.getSerializationConfig().setDateFormat(sdf);
try {
om.writeValue(outputStream, target);
} catch (JsonGenerationException e) {
throw e;
} catch (JsonMappingException e) {
throw e;
} catch (IOException e) {
throw e;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我遇到了同样的问题(使用 Jersey+Jackson+Json),客户端正在发送一个日期,但当数据映射到对象时,它在服务器中被更改。
我通过阅读此链接采用其他方法来解决此问题: http: //blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html,当我意识到收到的日期是一个时间戳(与阿德林在他的问题中相同:
“creationDate” ":1292236718456
)在我的 VO 类中,我将此注释添加到属性
@XmlJavaTypeAdapter
中,并且还实现了一个扩展了XmlAdapter
的内部类:我希望它能有所帮助也给你。
I had the same problem (using Jersey+Jackson+Json), the client was sending a date, but it was being changed in the server when the data was mapped into the object.
I followed other approach to solve this, by reading this link: http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html, when I realized that the date received was a TimeStamp (the same as Adrin in his question:
"creationDate":1292236718456
)In my VO class I added this annotation to the attribute
@XmlJavaTypeAdapter
and also implemented an inner class wich extendedXmlAdapter
:I hope it could help to you also.
下面的代码对我有用 - JAX-RS 1.1,Jersy 1.8
Below code worked for me - JAX-RS 1.1, Jersy 1.8
用这个重写 MessageBodyWriterJSON
Re-write the MessageBodyWriterJSON with this
我设法在 Resteasy“JAX-RS 方式”中做到这一点,因此它应该适用于每个兼容的实现,例如 Jersey(最近在 JEE7 服务器 Wildfly 8 上成功测试,它只需要对 Jackson 部分进行一些更改,因为他们更改了一些蜜蜂)。
您必须定义一个 ContextResolver (检查 Produces 是否包含正确的内容类型):
然后您必须在 javax.ws.rs.core.Application 的 getClasses 中返回新创建的类,
这样通过 jackson 进行的所有操作都会被赋予您的 ObjectMapper选择。
编辑:我最近发现,如果您决定扩展 JacksonConfigurator 以添加自定义映射,则使用 RestEasy 2.0.1(以及 Jackson 1.5.3)会出现奇怪的行为。
如果您只是这样做(当然将扩展类放入 RestApplication 中),则使用父类的映射器,也就是说您会丢失自定义映射。为了使其正常工作,我必须做一些对我来说似乎无用的事情:
I managed to do it in Resteasy "the JAX-RS way", so it should work on every compliant implementation like Jersey (recently successfully tested on JEE7 server Wildfly 8, it just required a few changes to the Jackson part because they changed a few APIs).
You must define a ContextResolver (check that Produces contains the correct content-type):
Then you must return the newly created class in your javax.ws.rs.core.Application's getClasses
this way all operation made through jackson are given the ObjectMapper of your choice.
EDIT: I recently found out at my expenses that using RestEasy 2.0.1 (and thus Jackson 1.5.3) there is a strange behaviour if you decide to extend the JacksonConfigurator to add custom mappings.
If you just do like this (and of course put the extended class in RestApplication) the mapper of the parent class is used, that is you lose the custom mappings. To make it correctly work I had to do something that seems useless to me otherwise:
要配置您自己的 ObjectMapper,您需要注入自己的实现 ContextResolver的类。
究竟如何让球衣接受这一点将取决于你的国际奥委会(弹簧,guice)。我使用 spring,我的类看起来像这样:
To configure your own ObjectMapper, you need to inject your own class that implements ContextResolver<ObjectMapper>
Exactly how to get jersey to pick this up will kind of depend on your IOC (spring, guice). I use spring, and my class looks something like this:
就其价值而言,该数字是标准 Java 时间戳(由 JDK 类使用); Unix 存储秒,Java 存储毫秒,这就是为什么它的值要大一些。
我希望有一些关于如何将 ObjectMapper 注入 Jersey 的文档(它应该遵循注入提供的对象的通常方法)。但是,您也可以重写 JacksonJaxRsProvider 来指定/配置 ObjectMapper 并注册它;这就是泽西岛本身所做的,并且有多种方法可以做到这一点。
For what it's worth, that number is standard Java timestamp (used by JDK classes); Unix stores seconds, Java milliseconds, which is why it's bit larger value.
I would hope there are some documents as to how to inject ObjectMapper into Jersey (it should follow the usual way to inject provided object). But alternatively you could override JacksonJaxRsProvider to specify/configure ObjectMapper and register that; this is what Jersey itself does, and there are multiple ways to do it.
如果您选择在服务器上使用 Joda DateTime 对象并希望序列化为 ISO8601,您可以使用 Jackson 的 JodaModule 。您可以按如下方式注册 Jersey 提供商:
更多信息请访问 Jersey 网站。
If you choose to work with Joda DateTime objects on your server and want to serialize to ISO8601 you could use Jackson's JodaModule. You can register a Jersey Provider as follows:
More information available on Jersey's website.