Make jackson serialize apache commons Pair

Viewed 6069

How can I make jackson, if even possible without making my own complex serializer of org.apache.commons.lang3.tuple.Pair, to serialize both my left and right object in a proper way. So for example I have to following code:

 public class MyPairTest {

    public static void main(String[] args) {
        Address address1 = new Address("Axel Street 1", "London");
        Address address2 = new Address("Axel Street 2", "Copenhagen");

        Map<String, Pair> map = new HashMap<>();
        map.put("Address", Pair.of(address1, address2));

        Pair p = Pair.of(address1, address2);

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        try {
            String serializeMapWithPair = mapper.writeValueAsString(map);
            String serializePair = mapper.writeValueAsString(p);
            System.out.println(serializeMapWithPair);
            System.out.println(serializePair);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        Gson gson = new Gson();
        System.out.println(gson.toJson(p));
    }
}

And the resulting output is:

{
  "Address" : {
    "com.example.api.beans.Address@224edc67" : {
      "street" : "Axel Street 2",
      "city" : "Copenhagen"
    }
  }
}
{
  "com.example.api.beans.Address@224edc67" : {
    "street" : "Axel Street 2",
    "city" : "Copenhagen"
  }
}
{"left":{"street":"Axel Street 1","city":"London"},"right":{"street":"Axel Street 2","city":"Copenhagen"}}

So the first two outputs are serializing Pair with jackson ObjectMapper where as the last is with Gson, I want to achieve the result as in the Gson example, but with jackson and without the left and right part. The Gson example I got from this jira improvement suggestion and I know that they state the following "Commons-lang has no dependencies, so Jackson or anything similar can not be used." But was wondering if Jackson them self have made a serializer or the kind for this, cannot find anything like it out there so maybe there is no simple solution to this with jackson? Or should I just drop it and use Gson, and then just manually manipulate and remove the left and right parts?

3 Answers

You can write a custom serializer:

private static final class PairSerializer extends JsonSerializer<Pair> {

    @Override
    public void serialize(Pair value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeObjectField("left", value.getLeft());
        gen.writeObjectField("right", value.getRight());
        gen.writeEndObject();
    }

}

and register it with your ObjectMapper:

mapper.registerModule(new SimpleModule().addSerializer(Pair.class, new PairSerializer()));

To answer the question with details:

Jackson treats the Pair<K,V> implements Map.Entry<K,V> as an item of a map and generates wrong output.

The only way to bypass is to write your own Pair class which NEVER implements the Map.Entry interface.

Related