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

Udo*_*eld 6 java rest date jax-rs jersey

我正在尝试将日期传递给JAX-RS服务。检查其他问题,例如:日期格式映射到JSON Jackson

答案和说明文件表明,有一个杰克逊注释应允许日期格式。

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

致电Rest-Service时,我得到了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)
Run Code Online (Sandbox Code Playgroud)

好像注释被忽略了。调试模式设置为EEE, dd MMM yyyy HH:mm:ss zzz和的解析方法EEE MMM d HH:mm:ss yyyy

我正在使用Spring 4.2.1,Jersey 2.22,它绑定了jackson 2.5.4。

如何获得使用正确格式分析的日期?

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

Pau*_*tha 5

参数转换是用ParamConverters完成的。如果您遵循堆栈跟踪,您将看到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";
Run Code Online (Sandbox Code Playgroud)

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

@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); 
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

这是使用Jersey 测试框架的完整测试用例

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是测试框架的依赖项

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)

也可以看看: