Dropwizard 如何知道如何序列化 Joda DateTime 对象,我该如何修改它?

How does Dropwizard know how to serialize Joda DateTime objects, and how can I modify it?

我正在查看使用 DropWizard 的 REST API。 DropWizard 似乎以某种方式神奇地知道如何将 joda DateTime 对象序列化为格式如下的字符串:

YYYY-MM-DD HH:MM:SS

但是如果我编写一个使用 ObjectMapper 来序列化 joda DateTime 对象的测试,我会得到类似这样的结果:

{"month_of_year":1,"hour_of_day":0,"minute_of_hour":15,"second_of_minute":3,"millis_of_second":0,"week_of_weekyear":3,"weekyear":2018,"year_of_era":2018,"year_of_century":18,"century_of_era":20,"millis_of_day":903000,"second_of_day":903,"minute_of_day":15,"day_of_year":18,"day_of_week":4,"day_of_month":18,"year":2018,"era":1,"millis":1516259703000,"chronology":{"zone":{"uncached_zone":{"cachable":true,"fixed":false,"id":"America/Denver"},"fixed":false,"id":"America/Denver"}},"zone":{"uncached_zone":{"cachable":true,"fixed":false,"id":"America/Denver"},"fixed":false,"id":"America/Denver"},"after_now":true,"before_now":false,"equal_now":false}

DropWizard 如何知道如何序列化它?

我序列化的字段是这样注释的:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-dd HH:mm:ss")
DateTime myDate;

我知道我在那里提供了格式字符串,但我想了解为什么 ObjectMapper(在我的测试中)不遵守它,而 DropWizard 遵守。 (注释是 Jackson 注释,而不是 DropWizard 注释,所以让我感到困惑的是 ObjectMapper.writeValue() 不会尊重它)。

查看 @JsonFormat 注释的来源时,我看到:

/**
 * Datatype-specific additional piece of configuration that may be used
 * to further refine formatting aspects. This may, for example, determine
 * low-level format String used for {@link java.util.Date} serialization;
 * however, exact use is determined by specific <code>JsonSerializer</code>
 */
public String pattern() default "";

这让我相信 Jackson 实际上并没有提供识别这个 pattern 属性的 JsonSerializer,同时让我相信 DropWizard 确实有这样一个 JsonSerializer。我怎样才能 configure/modify/override DropWizard 显然正在使用的 JsonSerializer

您的测试没有使用正确的ObjectMapper。 DW 在其 bootstrap 中将为您配置 ObjectMapper 合理的默认值(这是 DW 的全部——一切都有些合理和预先配置)。

因此,在您的情况下,您的测试需要使用 Jackson.newObjectMapper()。试试这个:

public static void main(String[] args) throws JsonProcessingException {

    ObjectMapper myMapper=  new ObjectMapper();
    ObjectMapper dwMapper = Jackson.newObjectMapper();
    System.out.println(myMapper.writeValueAsString(new X()));
    System.out.println(dwMapper.writeValueAsString(new X()));
}

public static class X { 
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-dd HH:mm:ss")
    DateTime now = DateTime.now();
}

将打印:

{"now":{"era":1,"dayOfYear":18,"dayOfWeek":4,"dayOfMonth":18,"year":2018,"weekOfWeekyear":3,"millisOfDay":37615193,"monthOfYear":1,"hourOfDay":10,"minuteOfHour":26,"secondOfMinute":55,"millisOfSecond":193,"weekyear":2018,"yearOfEra":2018,"yearOfCentury":18,"centuryOfEra":20,"secondOfDay":37615,"minuteOfDay":626,"zone":{"fixed":false,"uncachedZone":{"cachable":true,"fixed":false,"id":"Europe/London"},"id":"Europe/London"},"millis":1516271215193,"chronology":{"zone":{"fixed":false,"uncachedZone":{"cachable":true,"fixed":false,"id":"Europe/London"},"id":"Europe/London"}},"afterNow":false,"beforeNow":true,"equalNow":false}}
{"now":"2018-01-18 10:26:55"}

为了完整起见,这些是为您注册的模块:

private static ObjectMapper configure(ObjectMapper mapper) {
        mapper.registerModule(new GuavaModule());
        mapper.registerModule(new LogbackModule());
        mapper.registerModule(new GuavaExtrasModule());
        mapper.registerModule(new JodaModule());
        mapper.registerModule(new AfterburnerModule());
        mapper.registerModule(new FuzzyEnumModule());
        mapper.registerModules(new Jdk8Module());
        mapper.registerModules(new JavaTimeModule());
        mapper.setPropertyNamingStrategy(new AnnotationSensitivePropertyNamingStrategy());
        mapper.setSubtypeResolver(new DiscoverableSubtypeResolver());

        return mapper;
    }

这些在bootstrap中都是可以覆盖的。

请注意,我可能使用的是旧版本的 DW,因此最新版本可能略有不同。

阿图尔