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

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

问题描述

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



我想通过像这样的对象使用JSON进入JAX-RS方法:

  Person {
java.time.LocalDate birthDay;
}

我得到的例外是:


com.fasterxml.jackson.databind.JsonMappingException :找不到类型为[simple type,class <$ c $]的合适构造函数c> java.time.LocalDate ]:无法在[Source: io.undertow.servlet.spec]中实例化JSON对象(需要添加/启用类型信息?)。 ServletInputStreamImpl @ 21cca2c1 ; line:2,column:3]


如何创建某种将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注释。所以我们能做的就是写一个 XmlAdapter 将字符串转换为 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);
}
}

你可以选择你想要的任何格式,我只是用过 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;
}
}

如果您不想混淆模型类使用此注释,您只需在包级别声明注释。



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说没有依赖关系,但这是针对其他人的),你可以使用 jackson-datatype- jsr310 模块。查看完整解决方案 此处


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:

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]

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

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