1

I should be able to serialize/deserialize a org.springframework.data.util.pair to JSON / from JSON.

I have List<Pair<A, B>> myPairList - this list I like to store/load.

Serialization is no problem; however, since this pair is immutable, there is no default constructor and the deserialization fails.
I know that there is @JsonCreator; but if I am corretly, we can place it only on a constructor. Since pair class is final, I cannot extend it with an own default constructor annotated with @JsonCreator.
Can anybody point me out, how I can achieve my goal anyway? I would like to avoid creating an own wrapper class.

badera
  • 1,495
  • 2
  • 24
  • 49
  • I think you need to implement a custom deserializer for that attribute: https://stackoverflow.com/a/19167145/1905015 – markusw Oct 29 '18 at 15:27
  • I edited the question to point out that the `pair` is not in inside another POJO to serialize/deserialize. So where / how should I place `@JsonDeserialize`? – badera Oct 29 '18 at 15:36
  • OK, I can add the deserializer to the ObjectMapper. But I need to find out how to retrieve the fields correctly... – badera Oct 29 '18 at 16:31

2 Answers2

1

I think you need to implement a custom deserializer for that attribute like in this answer https://stackoverflow.com/a/19167145/1905015. You can place the @JsonDeserialize annotation above the attribute.

markusw
  • 1,975
  • 16
  • 28
1

The answer of markusw is correct. To show a real example, here is how I solved it finally to deserialize a List of Pairs:

public class MyPairDeserializer extends JsonDeserializer<Pair<MyClassA, MyClassB>> {

  static private ObjectMapper objectMapper = null;

  @Override
  public Pair<MyClassA, MyClassB> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
    if (objectMapper == null) {
      objectMapper = new ObjectMapper();
      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
    JsonNode treeNode = jsonParser.getCodec().readTree(jsonParser);
    MyClassA first = objectMapper.treeToValue(treeNode.get("first"), MyClassA.class);
    MyClassB second = objectMapper.treeToValue(treeNode.get("second"), MyClassB.class);
    return Pair.of(first, second);
  }

}

...
SimpleModule module = new SimpleModule();
module.addDeserializer(Pair.class, new MyPairDeserializer());
objectMapper.registerModule(module);
List<Pair<MyClassA, MyClassB>> myData = objectMapper.readValue(file..., new TypeReference<List<Pair<Class<MyClassA>, Class<MyClassB>>>>() {
...

Note the embedded ObjectMapper in the Deserializer. It is used to deserialize the "first" and "second" of the Pair.

badera
  • 1,495
  • 2
  • 24
  • 49