JAX-RS 和 java.time.LocalDate 作为输入参数 [英] JAX-RS and java.time.LocalDate as input parameter

查看:23
本文介绍了JAX-RS 和 java.time.LocalDate 作为输入参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 JAX-RS 和 java.time.LocalDate (java8) 的问题.

Problem using JAX-RS and java.time.LocalDate (java8).

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

I want to pass an object like this into a JAX-RS method using JSON:

Person {
  java.time.LocalDate birthDay;
}

我得到的例外是:

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

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 是另一个类中的 field,我必须编写一个 MessageBodyReader 为每个持有 LocalDate 的类(据我所知).

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(只使用 javaee-api,不需要任何第三方依赖)、JAX-RS、Java 8、Wildfly 8.2)

(Java EE7 (only using the javaee-api and don't want any third party dependencies), JAX-RS, Java 8, Wildfly 8.2)

有什么建议吗?

推荐答案

通常我会说为 Jackson 编写一个 Serializer/Deserializer,但由于您不想要任何其他依赖项,您可以使用 JAXB 解决方案.Jackson(带有 Resteasy)支持 JAXB 注释.所以我们能做的就是写一个 XmlAdapter 将字符串转换为 LocalDate.一个例子是这样的

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);
    }
}

你可以选择任何你想要的格式,我只是使用了 DateTimeFormatter.ISO_DATE,它基本上会寻找这种格式(2011-12-03).

You can choose any formatting you want, I just used the DateTimeFormatter.ISO_DATE, which will basically look for this format (2011-12-03).

然后您需要做的就是为该类型的 getter 字段注释

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.

在与模型类相同的包中的 package-info.java 文件中,添加这个

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;

<小时>

测试

@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 模块.在此处

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 作为输入参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆