问题描述
使用JAX-RS和 java.time.LocalDate
(java8)的问题。
我想通过像这样的对象使用JSON进入JAX-RS方法:
Person {
java.time.LocalDate birthDay;
}
我得到的例外是:
如何创建某种将json-dates映射到<$ c $的拦截器C> java.time.LocalDate ?我已经尝试实现 MessageBodyReader
,但是如果 LocalDate
是另一个类中的字段 ,我必须为每个持有 LocalDate
的类写一个 MessageBodyReader
(据我所知)。 / p>
(Java EE7(仅使用javaee-api,不需要任何第三方依赖),JAX-RS,Java 8,Wildfly 8.2)
有什么建议吗?
通常情况下我会写一个Serializer / Deserializer for杰克逊,但由于您不需要任何其他依赖项,您可以使用JAXB解决方案。 Jackson(带有Resteasy)支持JAXB注释。所以我们能做的就是写一个将字符串转换为 LocalDate
。一个例子就像是
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
公共类LocalDateAdapter扩展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);
}
}
你可以选择你想要的任何格式,我只是用过,基本上会寻找这种格式(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;
}
}
如果您不想混淆模型类使用此注释,您只需在包级别声明注释。
在 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()抛出异常{
WebTarget target = client.target(
TestPortProvider.generateURL (BASE_URI))路径( 日期)。
String person ={\birthDate \:\2015-01-04 \};
响应响应= target.request()。post(Entity.json(person));
System.out.println(response.readEntity(String.class));
response.close();
}
结果: 2015-01-04
UPDATE
同样适用于Jackson(我知道OP说没有依赖关系,但这是针对其他人的),你可以使用模块。查看完整解决方案
Problem using JAX-RS and java.time.LocalDate
(java8).
I want to pass an object like this into a JAX-RS method using JSON:
Person {
java.time.LocalDate birthDay;
}
The exception I get is:
How can I create some kind of an interceptor that maps json-dates to java.time.LocalDate
? I have tried implemented a MessageBodyReader
, but if the LocalDate
is a field in another class, I have to write a MessageBodyReader
for each class holding a LocalDate
(as far as I've understood).
(Java EE7 (only using the javaee-api and don't want any third party dependencies), JAX-RS, Java 8, Wildfly 8.2)
Any suggestions?
Normally I'd say to write a Serializer/Deserializer for Jackson, but since you don't want any other dependencies, you can use a JAXB solutions. Jackson (with Resteasy) comes with support for JAXB annotations. So what we can do is just write an XmlAdapter
to convert from the String to the LocalDate
. An example would be something like
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);
}
}
You can choose any formatting you want, I just used the DateTimeFormatter.ISO_DATE
, which will basically look for this format (2011-12-03).
Then all you need to do is annotate the field for getter of the type
public class Person {
private LocalDate birthDate;
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getBirthDate() { return birthDate; }
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
}
If you don't want to clutter your model classes with this annotation, then you can simply declare the annotation at the package level.
In a package-info.java
file in the same package as the model class(es), add this
@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;
Test
@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();
}
Result : 2015-01-04
UPDATE
Also for Jackson (I know the OP said without dependencies, but this is for others), you can use the jackson-datatype-jsr310 module. See full solution here
这篇关于JAX-RS和java.time.LocalDate作为输入参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!