Serialize a custom map with Jackson
jackson, java, json, serialization
Solution
You can leverage the @JsonAnySetter/ @JsonAnyGetter annotations, as described in this blog post. Since, as you mentioned, your custom map class must implement a Map interface, you could extract a separate "bean" interface and tell Jackson to use it instead when serializing via @JsonSerialize(as = ...) annotation.
I've slightly modified you example to illustrate how it could work. Note that if you want to deserialize the json string back to your map object, you may need to do some other tricks.
public class MapSerialize {
public static interface MyInterface {
String getSpecialInfo();
@JsonAnyGetter
Map<String, String> delegate();
}
@JsonSerialize(as = MyInterface.class)
public static class MyImpl extends ForwardingMap<String, String> implements MyInterface {
private String specialInfo;
private HashMap<String, String> delegate = new HashMap<String, String>();
public Map<String, String> delegate() {
return this.delegate;
}
@Override
public String getSpecialInfo() {
return specialInfo;
}
public void setSpecialInfo(String specialInfo) {
this.specialInfo = specialInfo;
}
@Override
public String put(String key, String value) {
return delegate.put(key, value);
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
MyImpl objectOfMapImpl = new MyImpl();
objectOfMapImpl.setSpecialInfo("specialInfo");
objectOfMapImpl.put("XXX", "YYY");
String json = mapper.writeValueAsString(objectOfMapImpl);
System.out.println(json);
}
}
Problem
I want to serialize a custom Map to JSON. The class with implements the map interface is the following: ``` public class MapImpl extends ForwardingMap<String, String> { //ForwardingMap comes from Guava private String specialInfo; private HashMap<String, String> delegate; @Override protected Map<String, String> delegate() { return this.delegate; } // some getters.... } ``` If I call now ``` ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(new File("/somePath/myJson.json"), objectOfMapImpl); ``` Jackson will serialize the map and ignores the variable `specialInfo` I tried some things with a custom implementation of `JsonSerializer` but I ended up with this snippet: ``` ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("someModule"); module.addSerializer(CheapestResponseDates.class, new JsonSerializer<MapImpl>() { @Override public void serialize(final MapImpl value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { CheapestResponseDurations.class); // how to serialize the map here? maybe be in a data node... jgen.writeStartObject(); jgen.writeObjectField("info", value.getInfo()); jgen.writeEndObject(); } }); mapper.registerModule(module); ``` I am using JDK 1.7 and Jackson 2.3.1