Jackson version: 2.9.8
I'm converting an object not to JSON, but to a Map, using objectMapper.convertValue(myObject, Map.class)
Here is a simple example to reproduce. My Pojo:
public static class Foo {
private final String string;
private final LocalDate date;
public Foo(String string, LocalDate date) {
this.string = string;
this.date = date;
}
public String getString() {
return string;
}
public LocalDate getDate() {
return date;
}
}
Conversion code:
public static void main(String[] args) {
Foo foo = new Foo("hello", LocalDate.of(1999, 12, 31));
ObjectMapper objectMapper = new ObjectMapper();
Map map = objectMapper.convertValue(foo, Map.class);
Object string = map.get("string");
System.out.println("string: >>>"+ string +"<<< of type "+ string.getClass().getName());
Object date = map.get("date");
System.out.println("date: >>>"+ date +"<<< of type "+ date.getClass().getName());
}
This prints:
string: >>>hello<<< of type java.lang.String
date: >>>{year=1999, month=DECEMBER, chronology={id=ISO, calendarType=iso8601}, era=CE, dayOfMonth=31, dayOfWeek=FRIDAY, dayOfYear=365, leapYear=false, monthValue=12}<<< of type java.util.LinkedHashMap
When enabling the JavaTimeModule with
objectMapper.registerModule(new JavaTimeModule());
it prints:
string: >>>hello<<< of type java.lang.String
date: >>>[1999, 12, 31]<<< of type java.util.ArrayList
But what I need is to KEEP the LocalDate instance in the Map. No conversion. I can't find how to configure Jackson to keep (not convert) a type.
I have tried with a noop converter:
private static class KeepLocalDateJsonSerializer extends JsonSerializer<LocalDate> {
@Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeObject(localDate);
}
};
registering it with
SimpleModule mod = new SimpleModule("KeepLocalDate");
mod.addSerializer(LocalDate.class, new KeepLocalDateJsonSerializer());
objectMapper.registerModule(mod);
and this leads to a StackOverflowError with detail:
ReadOnlyClassToSerializerMap.typedValueSerializer(ReadOnlyClassToSerializerMap.java:85)
JsonMappingException: Infinite recursion $Foo["date"]
Apparently Jackson tries to convert the returned value also. Looks like a bug to me. If the converter writes the same object through, even the same instance, then obviously the intention is to keep it. When converting to JSON then I understand we can't keep a LocalDate instance, but in a Map that's not the case.
How can I achieve this, in a generic way, so that it works for any data structure? Without annotations in the Pojo. So that all instances of a certain data type are passed through untouched.
There is this similar question Jackson Convert Object to Map preserving Date type but it's 5 years old, uses Date not LocalDate, and the solution with SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
does not work here.