如何将Java Calendar对象的JSON表示传递给REST服务?

问题描述 投票:2回答:4

这里是我的问题的简化版本。考虑以下REST服务...

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

当然,这个...

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

}

我正在使用邮递员,起初我通过向'http://localhost:8080/ProjectName/rest/test/getCalendar'发送GET请求来获得Calendar对象的JSON表示形式。然后,我复制要返回的JSON,这是

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

然后使用邮递员,将上面返回给我的数据发送到POST到'http://localhost:8080/ProjectName/rest/'。然后会抛出“ javax.ws.rs.NotSupportedException:无法使用内容类型”。

如何解决此问题,以便该服务可以处理Calendar对象(以及将Calendar对象作为字段的类)?

编辑:

是,我正在设置正确的内容类型为application / json。

这是我得到的答复...

com.fasterxml.jackson.databind.JsonMappingException:无法从START_OBJECT令牌中反序列化java.util.Calendar的实例在[来源:io.undertow.servlet.spec.ServletInputStreamImpl@4cf87599;行:1,列:1]

更新:为了使其正常工作,我使用了@peeskillets解决方案。

java json calendar jackson jax-rs
4个回答
3
投票

Jackson通常仅适用于JavaBean样式的POJO,而Calendar则不行。对于这些情况,Jackson允许我们创建自定义反序列化器。创建解串器后,可以在ObjectMapper中将其注册到ContextResolver中。例如

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

我们可以通过ObjectMapper进行注册

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

要在我们的JAX-RS应用程序中使用ObjectMapper,我们可以在ContextResolver中创建它,如here所示。如果尚未添加jackson-databind,则需要将其添加为依赖项。

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

请注意,上述依赖关系已经随JAX-RS的Jackson JSON提供程序一起提供,因此,如果您已经具有Jackson JSON支持的依赖关系,则将不再需要它。

我已经使用您提供的JSON对它进行了测试,并且效果很好。

查看有关自定义解串器here的更多信息>


1
投票

您需要在请求中传递正确的内容类型,并检查是否给出了正确的路径。


0
投票

因此,在进行了一些研究之后,并感谢那些回答者(特别是@peeskillet,我为这个问题提出了两种解决方案。


0
投票

我知道这是个老问题,但是我只是添加了一个长的而不是Calendar的构造函数,因此可以反序列化

© www.soinside.com 2019 - 2024. All rights reserved.