用于JAX-RS服务中的日期解析的@JsonFormat将被忽略

时间:2015-09-30 10:15:05

标签: java rest date jersey jax-rs

我正在尝试将日期传递给JAX-RS服务。检查其他问题,例如:Date format Mapping to JSON Jackson

答案和文档显示,jackson annotation应该允许日期格式化。

SKU_ID

在致电Rest-Service后,我得到public class SolutionFilter { @MatrixParam("toDate") @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd", timezone="CET") private Date toDate; public void setToDate(Date toDate) { this.toDate = toDate; } }

ParseException

似乎忽略了注释。调试解析方法时,模式设置为Caused by: java.text.ParseException: Unparseable date: "2016-01-01" at java.text.DateFormat.parse(DateFormat.java:366) at org.glassfish.jersey.message.internal.HttpDateFormat.readDate(HttpDateFormat.java:137) at org.glassfish.jersey.server.internal.inject.ParamConverters$DateProvider$1.fromString(ParamConverters.java:259) EEE, dd MMM yyyy HH:mm:ss zzz

我使用的是Spring 4.2.1,Jersey 2.22,它绑定了杰克逊2.5.4。

如何使用正确的模式解析日期?

更新:进一步思考它,JSON仅用于输出解析。但这可能与JAX-RS参数解析有关。

1 个答案:

答案 0 :(得分:3)

Param转换是使用ParamConverter完成的。如果您关注堆栈跟踪,您将看到ParamConverters$DateProvider。下一个调用是进行解析的HttpDateFormat类。

如果查看课程顶部,您将看到支持的日期格式。这些是标准的HTTP数据格式

/**
 * The date format pattern for RFC 1123.
 */
private static final String RFC1123_DATE_FORMAT_PATTERN = "EEE, dd MMM yyyy HH:mm:ss zzz";
/**
 * The date format pattern for RFC 1036.
 */
private static final String RFC1036_DATE_FORMAT_PATTERN = "EEEE, dd-MMM-yy HH:mm:ss zzz";
/**
 * The date format pattern for ANSI C asctime().
 */
private static final String ANSI_C_ASCTIME_DATE_FORMAT_PATTERN = "EEE MMM d HH:mm:ss yyyy";

据我所知或可以说,我们可以添加到此列表中没有可用的配置。唯一的另一种选择是编写自己的转换器。例如

@Provider
public class DateParamConverterProvider implements ParamConverterProvider {

    private final String format;

    public DateParamConverterProvider(String dateFormat) {
        this.format = dateFormat;
    }

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> rawType, 
                                              Type genericType, 
                                              Annotation[] annotations) {

        if (rawType != Date.class) { return null; }

        return (ParamConverter<T>) new ParamConverter<Date>() {

            @Override
            public Date fromString(String value) {
                SimpleDateFormat formatter = new SimpleDateFormat(format);
                try {
                    return formatter.parse(value);
                } catch (Exception ex) {
                    throw new WebApplicationException("Bad formatted date", 400);
                }
            }

            @Override
            public String toString(Date date) { 
                return new SimpleDateFormat(format).format(date); 
            }
        };
    }
}

以下是使用Jersey Test Framework

的完整测试用例
public class DateParamTest extends JerseyTest {

    private static final String FORMAT = "MM-dd-yyyy";

    @Path("date")
    public static class DateResource {
        @GET
        public String get(@MatrixParam("since") Date date) {
            return new SimpleDateFormat(FORMAT).format(date);
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(DateResource.class)
                .register(new DateParamConverterProvider(FORMAT));
    }

    @Test
    public void should_return_same_date_and_format() {
        final String date = "09-30-2015";
        Response response = target("date").matrixParam("since", date)
                .request().get();
        assertEquals(200, response.getStatus());
        String returnDate = response.readEntity(String.class);
        assertEquals(date, returnDate);
        System.out.println(returnDate);
    }
}

以下是测试框架的依赖关系

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>

另见: