Json 如何将Joda DateTime对象作为HTTP POST的消息体传递给Jersey REST端点?
我想将org.joda.time.DateTime作为json帖子的消息体传递给Jersey端点。我的球衣用的是莫西。我已经创建了一个自定义XmlAdapter来实现这一点,但我不清楚如何连接这个适配器。我发现的自定义适配器示例在要发布的对象上使用注释,但我不能这样做(我不能在DateTime类上放置注释,因为我不能操作它的源代码) 我正在使用Jersey测试框架来测试这一点 我的球衣终点:Json 如何将Joda DateTime对象作为HTTP POST的消息体传递给Jersey REST端点?,json,jaxb,jersey,jodatime,moxy,Json,Jaxb,Jersey,Jodatime,Moxy,我想将org.joda.time.DateTime作为json帖子的消息体传递给Jersey端点。我的球衣用的是莫西。我已经创建了一个自定义XmlAdapter来实现这一点,但我不清楚如何连接这个适配器。我发现的自定义适配器示例在要发布的对象上使用注释,但我不能这样做(我不能在DateTime类上放置注释,因为我不能操作它的源代码) 我正在使用Jersey测试框架来测试这一点 我的球衣终点: @POST @Path("/{memberId}") @Produces(MediaType.APPLI
@POST
@Path("/{memberId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ResultBean recordDate(@PathParam("memberId") Long memberId, DateTime dateTime) {
// TODO stuff happens
return new ResultBean(memberId, dateTime);
}
我的球衣测试:
public class FooEndpointImplTest extends JerseyTest {
@Test
public void testWithDate() {
Long memberId = 1L;
DateTime date = new DateTime();
Entity<DateTime> dateEntity = Entity.json(date);
ResultBean result = target(
"/" + memberId)
.request().post(dateEntity, ResultBean.class);
assertNotNull(result);
}
}
public类测试扩展了JerseyTest{
@试验
public void testWithDate(){
长成员ID=1L;
DateTime日期=新的日期时间();
实体dateEntity=Entity.json(日期);
结果Bean结果=目标(
“/”+成员ID)
.request().post(dateEntity,ResultBean.class);
assertNotNull(结果);
}
}
和我的适配器:
package foo;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.DateTime;
public class DateTimeAdapter extends XmlAdapter<String, DateTime> {
@Override
public DateTime unmarshal(String v) throws Exception {
Long millis = Long.parseLong(v);
return new DateTime(millis);
}
@Override
public String marshal(DateTime v) throws Exception {
return Long.toString(v.getMillis());
}
}
package-foo;
导入javax.xml.bind.annotation.adapters.XmlAdapter;
导入org.joda.time.DateTime;
公共类DateTimeAdapter扩展了XmlAdapter{
@凌驾
公共DateTime解组器(字符串v)引发异常{
Long-millis=Long.parseLong(v);
返回新的日期时间(毫秒);
}
@凌驾
公共字符串封送处理程序(DateTime v)引发异常{
返回Long.toString(v.getMillis());
}
}
当我按原样运行这个测试时,我得到一个500错误。第一件事:您需要一个用于joda DateTime的
MessageBodyReader/Writer
如果没有一些调整,JSON序列化日期时间的POST看起来将无法工作。Gson序列化的日期时间如下所示:
{ "iMillis": 1414507195233,
"iChronology": {
"iBase": {
"iBase": {
...
},
"iParam": {
...
}}}}
如果您尝试使用Gson再次反序列化它,Gson将失败,因为org.joda.time.Chronology
->iChronology
没有默认的非arg构造函数,Gson需要反序列化该对象。Afaig,在使用任何标准反序列化程序反序列化DateTime时,您都会遇到这样的问题
因此,我最终创建了基于
阅读器:
/。。。
导入org.joda.time.DateTime;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.datatype.joda.JodaModule;
@使用(MediaType.APPLICATION_JSON)
公共类JodaTimeBodyReader实现MessageBodyReader{
私有静态ObjectMapper mapper=新ObjectMapper();
公共JodaTimeBodyReader(){
registerModule(新的JodaModule());
}
@凌驾
公共布尔值可读取(类类型、类型genericType、注释[]注释、MediaType MediaType){
返回类型==DateTime.class;
}
@凌驾
public DateTime readFrom(类类型、类型genericType、注释[]注释、MediaType MediaType、多值Map HttpHeader、InputStream entityStream)引发IOException、WebApplicationException{
试一试{
返回mapper.readValue(entityStream,DateTime.class);
}捕获(例外e){
抛出新的ProcessingException(“反序列化org.joda.time.DateTime时出错。”,e);
}
}
}
作者:
/。。。
导入org.joda.time.DateTime;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.datatype.joda.JodaModule;
@提供者
@使用(MediaType.APPLICATION_JSON)
公共类JodaTimeBodyWriter实现MessageBodyWriter{
私有静态ObjectMapper mapper=新ObjectMapper();
公共JodaTimeBodyWriter(){
registerModule(新的JodaModule());
}
@凌驾
公共布尔值可写(类类型、类型genericType、注释[]注释、MediaType MediaType){
返回类型==DateTime.class;
}
@凌驾
public long getSize(日期时间t、类类型、类型genericType、注释[]注释、MediaType MediaType){
//JAX-RS 2.0已弃用,Jersey运行时已忽略
返回0;
}
@凌驾
public void writeTo(日期时间t、类类型、类型genericType、注释[]注释、MediaType MediaType、多值Map HttpHeader、OutputStream entityStream)引发IOException、WebApplicationException{
试一试{
write(mapper.writeValueAsBytes(t));
}捕获(例外e){
抛出新的ProcessingException(“将org.joda.time.DateTime序列化到输出流时出错”,e);
}
}
}
两者都在ResourceConfig中注册
编写器将以1414507195233(yap,而不是JSON)进行响应,如果您将其发回资源,您将获得有效的DateTime
如果您获得了一个JSON,就像我上面的示例一样,那么现在可以升级读取器来解析iMillis的JSON并使用Long值。对于时区,您也可以使用dateTime.withZone(…)
来设置值
我使用过的Maven依赖项:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.4.0</version>
</dependency>
乔达时间
乔达时间
2.5
com.fasterxml.jackson.datatype
jackson数据类型joda
2.4.0
泽西岛2.12
希望这能有所帮助 而不是:
@POST
@Path("/{memberId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ResultBean recordDate(@PathParam("memberId") Long memberId, DateTime dateTime) {
// TODO stuff happens
return new ResultBean(memberId, dateTime);
}
你可以做:
@POST
@Path("/{memberId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ResultBean recordDate(@PathParam("memberId") Long memberId, DateTimeWrapper dateTimeWrapper) {
// TODO stuff happens
return new ResultBean(memberId, dateTime);
}
其中DateTimeWrapper
看起来像。由于DateTime
对象现在是一个属性,而不是顶层,因此XmlAdapter
将应用
@XmlAccessorType(XmlAccessType.FIELD)
public class DateTimeWrapper {
@XmlValue
@XmlJavaTypeAdapter(YourDateTimeAdapter.class)
private DateTime value;
}
Jackson和MOXy是两个不同的JSON提供者。我不明白你的意思。问题是如何通过,而不是如何通过与莫西。你的解决方案将工作,但是,它需要杰克逊,而OP写“我的球衣使用莫西”。错误是什么?你能给我们看看stacktrace吗?谢谢@Blaise,这肯定会有用的。我希望找到一种不用添加任何包装的方法。考虑到我找不到只使用config的方法,这可能是最好的方法。@MarkS-您可以编写自己的
MessageBodyReader
/MessageBodyWriter
,但您需要