Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass JSON representations of Java Calendar objects to REST service?

Here is a simplified version of my problem. Consider the following REST services...

@Stateless
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/test")
public class TestResource {


    @POST
    public Response test(Calendar c) {
        System.out.println(c);
        return Response.ok(Response.Status.OK).build();
    }

    @GET
    @Path("/getCalendar")
    public Response getCalendar() {
        return Response.ok(toJSONString(Calendar.getInstance())).build();
    }

    public String toJSONString(Object object) {
        GsonBuilder builder = new GsonBuilder();
        builder.setDateFormat("yyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        Gson gson = builder.create();
        return gson.toJson(object);
    }
}

and of course, this...

@ApplicationPath("/rest")
public class RestActivator extends Application {

}

I am using Postman, and at first I get a JSON representation of the Calendar object by sending a GET request to 'http://localhost:8080/ProjectName/rest/test/getCalendar'. I then copy the JSON that gets returned which is

{
  "year": 2015,
  "month": 5,
  "dayOfMonth": 29,
  "hourOfDay": 10,
  "minute": 7,
  "second": 24
}

Then using Postman I send a POST to 'http://localhost:8080/ProjectName/rest/' with the data that was returned to me above. Then the 'javax.ws.rs.NotSupportedException: Cannot consume content type' gets thrown.

How can I fix this so the service can handle Calendar objects (and classes that have Calendar objects as fields)?

Edit:

Yes I am setting the correct content type which is application/json.

Here is the response I am getting...

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.Calendar out of START_OBJECT token at [Source: io.undertow.servlet.spec.ServletInputStreamImpl@4cf87599; line: 1, column: 1]

Update: To get this to work I used @peeskillets solution.

like image 260
Rob L Avatar asked Oct 30 '25 17:10

Rob L


1 Answers

Jackson generally only works with JavaBean style POJOs, which Calendar is not. For these cases, Jackson allows us to create custom Deserializers. Once we create the deserializer, we can register it with the ObjectMapper in a ContextResolver. For example

public class CalendarDeserializer extends JsonDeserializer<Calendar>  {

    @Override
    public Calendar deserialize(JsonParser jp, DeserializationContext dc) 
            throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        int year = getInt("year", node);
        int month = getInt("month", node);
        int dayOfMonth = getInt("dayOfMonth", node);
        int hourOfDay = getInt("hourOfDay", node);
        int minute = getInt("minute", node);
        int second = getInt("second", node);

        Calendar c = Calendar.getInstance();
        c.set(year, month, dayOfMonth, hourOfDay, minute, second);
        return c;
    }

    private int getInt(String name, JsonNode node) {
        return (Integer) ((IntNode) node.get(name)).numberValue();
    } 
}

To register it with the ObjectMapper we can do

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Calendar.class, new CalendarDeserializer());
mapper.registerModule(module);

To use the ObjectMapper with our JAX-RS application, we can create it in the ContextResolver, as seen here. You will need to add the jackson-databind as a dependency, if you don't already have it.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson2.version}</version>
</dependency>

Note that the above dependency already comes with Jackson JSON providers for JAX-RS, so if you already have Jackson JSON support dependency, you won't need it.

I've tested this with the JSON you have provided, and it works fine.

See more about custom deserializers here

like image 106
Paul Samsotha Avatar answered Nov 01 '25 08:11

Paul Samsotha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!