Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
791 views
in Technique[技术] by (71.8m points)

json - JAX-RS and java.time.LocalDate as input parameter

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...