Internally, I use a map for a quick lookup of values, e.g. private Map<String, CustomObject> lookupTable
, where the CustomObject
has some id
field that is being used as the key in the lookupTable
. It is silly to serialize the map's keys, so I want to annotate the internal variable to serialize only the values. This doesn't work, obviously:
@JsonSerialize(as = List.class)
private final Map<String, CustomObject> lookupTable;
Why a custom serializer won't work
I created a custom serializer like:
public static class MapValuesJsonSerializer extends JsonSerializer<Map<?, ?>> {
@Override
public void serialize(
Map<?, ?> value,
JsonGenerator generator,
SerializerProvider provider)
throws IOException, JsonProcessingException {
generator.writeObject(value.values());
}
}
Then, I annotated the field accordingly:
@JsonSerialize(using = MapValuesJsonSerializer.class)
public Map<String, CustomObject> lookupTable;
This works with some Java test code, but it breaks when using MongoDB's driver and MongoJack. I get some unhelpful exception, which I believe is because it is not actually serializing the returned object and is, instead, just trying to pass that raw object to the BSON serializer:
Caused by: java.lang.IllegalArgumentException: can't serialize class CustomObject
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270)
at org.bson.BasicBSONEncoder.putIterable(BasicBSONEncoder.java:295)
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:234)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120)
at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
at com.mongodb.OutMessage.putObject(OutMessage.java:289)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
at com.mongodb.DBCollection.insert(DBCollection.java:148)
at com.mongodb.DBCollection.insert(DBCollection.java:91)
at org.mongojack.JacksonDBCollection.insert(JacksonDBCollection.java:255)
// My code (not the serializer)...