JAX-RS 和 java.time.LocalDate 作为输入参数

2022-09-03 12:42:04

使用 JAX-RS 和 (java8) 时出现问题。java.time.LocalDate

我想使用JSON将这样的对象传递到JAX-RS方法中:

Person {
  java.time.LocalDate birthDay;
}

我得到的例外是:

com.fasterxml.jackson.databind.JsonMappingException:找不到适合类型 [简单类型,类 ]的构造函数:无法从 JSON 对象实例化(需要添加/启用类型信息?) 在 [来源: ; 行: 2, 列: 3]java.time.LocalDateio.undertow.servlet.spec.ServletInputStreamImpl@21cca2c1

如何创建某种将 json 日期映射到的拦截器?我尝试过实现一个,但是如果是另一个类中的字段,我必须为每个持有a的类写一个(据我所知)。java.time.LocalDateMessageBodyReaderLocalDateMessageBodyReaderLocalDate

(Java EE7(只使用javaee-api,不需要任何第三方依赖),JAX-RS,Java 8,Wildfly 8.2)

有什么建议吗?


答案 1

通常我会说为Jackson编写一个序列化程序/反序列化程序,但是由于您不需要任何其他依赖项,因此您可以使用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;
    }
}

如果不想用这个注释来混淆模型类,那么只需在包级别声明注释即可。

在与模型类(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模块。在此处查看完整解决方案


答案 2