JAX-RS 和 java.time.LocalDate 作为输入参数
JAX-RS and java.time.LocalDate as input parameter
使用 JAX-RS 和 java.time.LocalDate
(java8) 时出现问题。
我想使用 JSON 将这样的对象传递到 JAX-RS 方法中:
Person {
java.time.LocalDate birthDay;
}
我得到的异常是:
com.fasterxml.jackson.databind.JsonMappingException
: No suitable constructor found for type [simple type, class java.time.LocalDate
]: can not instantiate from JSON object (need to add/enable type information?) at [Source: io.undertow.servlet.spec.ServletInputStreamImpl@21cca2c1
; line: 2, column: 3]
如何创建某种将 json-dates 映射到 java.time.LocalDate
的拦截器?我已经尝试实现 MessageBodyReader
,但是如果 LocalDate
是另一个 class 中的 字段 ,我必须写一个 MessageBodyReader
对于每个持有 LocalDate
的 class(据我所知)。
(Java EE7(仅使用 javaee-api,不需要任何第三方依赖项),JAX-RS,Java 8,Wildfly 8.2)
有什么建议吗?
通常我会说为 Jackson 写一个 Serializer/Deserializer,但由于您不需要任何其他依赖项,您可以使用 JAXB 解决方案。 Jackson(带有 Resteasy)支持 JAXB 注释。所以我们能做的就是写一个 XmlAdapter
来从 String 转换成 LocalDate
。例如
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
@Override
public LocalDate unmarshal(String dateString) throws Exception {
return LocalDate.parse(dateString, DateTimeFormatter.ISO_DATE);
}
@Override
public String marshal(LocalDate localDate) throws Exception {
return DateTimeFormatter.ISO_DATE.format(localDate);
}
}
你可以选择任何你想要的格式,我只是使用了DateTimeFormatter.ISO_DATE
,它基本上会寻找这种格式(2011-12-03)。
然后您需要做的就是为 getter 类型的字段添加注释
public class Person {
private LocalDate birthDate;
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getBirthDate() { return birthDate; }
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
}
如果您不想使用此注释使您的模型 classes 混乱,那么您可以简单地在包级别声明注释。
在与模型 class(es) 相同的包中的 package-info.java
文件中,添加此
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(type = LocalDate.class,
value = LocalDateAdapter.class)
})
package thepackage.of.the.models;
import java.time.LocalDate;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
测试
@Path("/date")
public class DateResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response postPerson(Person person) {
return Response.ok(DateTimeFormatter.ISO_DATE.format(
person.getBirthDate())).build();
}
}
@Test
public void testResteasy() throws Exception {
WebTarget target = client.target(
TestPortProvider.generateURL(BASE_URI)).path("date");
String person = "{\"birthDate\":\"2015-01-04\"}";
Response response = target.request().post(Entity.json(person));
System.out.println(response.readEntity(String.class));
response.close();
}
结果:2015-01-04
更新
同样对于 Jackson(我知道 OP 说没有依赖项,但这适用于其他人),您可以使用 jackson-datatype-jsr310 module. See full solution
使用 JAX-RS 和 java.time.LocalDate
(java8) 时出现问题。
我想使用 JSON 将这样的对象传递到 JAX-RS 方法中:
Person {
java.time.LocalDate birthDay;
}
我得到的异常是:
com.fasterxml.jackson.databind.JsonMappingException
: No suitable constructor found for type [simple type, classjava.time.LocalDate
]: can not instantiate from JSON object (need to add/enable type information?) at [Source:io.undertow.servlet.spec.ServletInputStreamImpl@21cca2c1
; line: 2, column: 3]
如何创建某种将 json-dates 映射到 java.time.LocalDate
的拦截器?我已经尝试实现 MessageBodyReader
,但是如果 LocalDate
是另一个 class 中的 字段 ,我必须写一个 MessageBodyReader
对于每个持有 LocalDate
的 class(据我所知)。
(Java EE7(仅使用 javaee-api,不需要任何第三方依赖项),JAX-RS,Java 8,Wildfly 8.2)
有什么建议吗?
通常我会说为 Jackson 写一个 Serializer/Deserializer,但由于您不需要任何其他依赖项,您可以使用 JAXB 解决方案。 Jackson(带有 Resteasy)支持 JAXB 注释。所以我们能做的就是写一个 XmlAdapter
来从 String 转换成 LocalDate
。例如
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
@Override
public LocalDate unmarshal(String dateString) throws Exception {
return LocalDate.parse(dateString, DateTimeFormatter.ISO_DATE);
}
@Override
public String marshal(LocalDate localDate) throws Exception {
return DateTimeFormatter.ISO_DATE.format(localDate);
}
}
你可以选择任何你想要的格式,我只是使用了DateTimeFormatter.ISO_DATE
,它基本上会寻找这种格式(2011-12-03)。
然后您需要做的就是为 getter 类型的字段添加注释
public class Person {
private LocalDate birthDate;
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getBirthDate() { return birthDate; }
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
}
如果您不想使用此注释使您的模型 classes 混乱,那么您可以简单地在包级别声明注释。
在与模型 class(es) 相同的包中的 package-info.java
文件中,添加此
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(type = LocalDate.class,
value = LocalDateAdapter.class)
})
package thepackage.of.the.models;
import java.time.LocalDate;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
测试
@Path("/date")
public class DateResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response postPerson(Person person) {
return Response.ok(DateTimeFormatter.ISO_DATE.format(
person.getBirthDate())).build();
}
}
@Test
public void testResteasy() throws Exception {
WebTarget target = client.target(
TestPortProvider.generateURL(BASE_URI)).path("date");
String person = "{\"birthDate\":\"2015-01-04\"}";
Response response = target.request().post(Entity.json(person));
System.out.println(response.readEntity(String.class));
response.close();
}
结果:2015-01-04
更新
同样对于 Jackson(我知道 OP 说没有依赖项,但这适用于其他人),您可以使用 jackson-datatype-jsr310 module. See full solution