FasterXML / jackson-modules-java8

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
Apache License 2.0
398 stars 116 forks source link

Q on Serializing java.time dates w/o nano parts #312

Open mebigfatguy opened 2 months ago

mebigfatguy commented 2 months ago

Hi folks, i'm trying to get interop between joda and java.time while i try to switch over to java.time. So currently we have a bajillion pojos that hold joda DateTimes that get serialized to ISO strings to the browser.

I'd like to start incrementally switching that over to LocalDateTime for some of them. When i add the JavaTimeModule,

    m_mapper.registerModule(new JavaTimeModule());

i see that the nano part of the date is written to the date string as well, which is not what our current Joda serializer does, so

I'm asking to see how to configure the JavaTimeModule to not write the nano time, from what i can tell it's just picks a static one, but perhaps i missed something??

    return DateTimeFormatter.ISO_LOCAL_DATE_TIME;
mebigfatguy commented 2 months ago

ok, i futz around some, and came up with this. Is this rational?

public class Tester {

    public static final DateTimeFormatter ISO_OPC_LOCAL_DATE_TIME;
    static {
        // @formatter:off
        ISO_OPC_LOCAL_DATE_TIME = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral('T')
                .appendValue(HOUR_OF_DAY, 2)
                .appendLiteral(':')
                .appendValue(MINUTE_OF_HOUR, 2)
                .appendLiteral(':')
                .appendValue(SECOND_OF_MINUTE, 2)
                .toFormatter();
        // @formatter:on
    }

    @Test
    public void test() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule().addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(ISO_OPC_LOCAL_DATE_TIME)));
        String now = mapper.writeValueAsString(LocalDateTime.now());
        System.out.println(now);

    }
}
cowtowncoder commented 2 months ago

That should work.

One thing is that a recommended approach would be to add "config override" for type LocalDateTime.class instead of constructing deserializer explicitly. From tests, it's something like:

        ObjectMapper m = mapperBuilder().withConfigOverride(LocalDateTime.class,
                cfg -> cfg.setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd'X'HH:mm")))
            .build();

and is basically more robust way, in case LocalDateTimeSerializer implementation changed.