I am trying to serialize Java objects to JSON. One of my Java objects has a JodaTime LocalTime
object as one of its fields.
A fair number of my Java objects also have various fields that are Collection
s that could be empty. I want to prevent the serialization of JSON that looks like this:
{id: 2348904, listOfThings: [], listOfStuff: [], nowASet: []}
In this scenario where those three Collection
s are empty, I would rather see this JSON:
{id: 2348904}
The correct way to do such a thing is to configure the ObjectMapper
with the following line of code:
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
This works just fine...until I hit that Java object with the LocalTime
inside of it. That's when I get an actual java.lang.StackOverflowError
.
It seems to be ping-ponging between JodaDateSerializerBase.isEmpty()
and JsonSerializer.isEmpty()
. I'm not sure how, though, because they don't call each other.
I managed to make a SSSSSSCCCCEEEE, or whatever the hell the acronym is, as follows:
package whatever.you.like;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.joda.time.LocalTime;
import org.junit.Test;
public class TestClass {
public class JodaMapper extends ObjectMapper {
private static final long serialVersionUID = 34785437895L;
public JodaMapper() {
registerModule(new JodaModule());
}
public boolean getWriteDatesAsTimestamps() {
return getSerializationConfig().isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
public void setWriteDatesAsTimestamps(boolean state) {
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, state);
}
}
private class Thing {
private LocalTime localTime;
public Thing() {}
public void setLocalTime(LocalTime localTime) {
this.localTime = localTime;
}
public LocalTime getLocalTime() {
return localTime;
}
}
@Test
public void extendObjectMapperTest() throws JsonProcessingException {
JodaMapper objectMapper = new JodaMapper();
objectMapper.setWriteDatesAsTimestamps(false);
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
Thing thing = new Thing();
LocalTime localTime = new LocalTime(12389340L);
thing.setLocalTime(localTime);
System.out.println("Never manages to print this out: " + objectMapper.writeValueAsString(thing));
}
@Test
public void configureObjectMapperTest() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JodaModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
Thing thing = new Thing();
LocalTime localTime = new LocalTime(12389340L);
thing.setLocalTime(localTime);
System.out.println("Never manages to print this out: " + objectMapper.writeValueAsString(thing));
}
}
I tried both extending the ObjectMapper
and configuring the ObjectMapper
, and I get the same error each time.
Dependencies:
Interestingly, you can find in that GitHub a unit test ("testLocalDateSer()
") that claims to succeed using the Include.NON_EMPTY
qualifier. I fail to see how it could possibly function.
Upgrade to
This works.
@Test
public void configureObjectMapperTest() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JodaModule());
// objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
Thing thing = new Thing();
LocalTime localTime = new LocalTime(12389340L);
thing.setLocalTime(localTime);
System.out.println("Never manages to print this out: " + objectMapper.writeValueAsString(thing));
}