Как разобрать список пар из json с помощью FasterXML

Предположим, у меня есть следующий класс Java:

import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Demo {
    public int x;
    public int y;
    public List<Pair<Integer, Integer>> the_list;
}

Я хотел бы заполнить его, например. следующий формат json:

{ "x" : 1,  
  "y" : 2, 
  "the_list" : [[1,2],[3,4]]}

используя более быстрый xml

ObjectMapper mapper = new ObjectMapper();

Вероятно, я смогу добраться туда, вызвав mapper.readTree(json) и заполнив все, что мне нужно. Проблема в том, что реальный класс, который у меня есть (не демо), содержит много параметров, и я хотел бы извлечь выгоду из возможностей привязки данных.

Попытка равнины:

mapper.readValue(json, Demo.class)

дает следующую ошибку:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of     
org.apache.commons.lang3.tuple.Pair, problem: abstract types either need to be mapped to 
concrete types, have custom deserializer, or be instantiated with additional type   
information

Есть ли способ смешать пользовательский синтаксический анализ с привязкой данных? Я просмотрел аннотации, но не нашел ничего подходящего для этой цели (мне не удалось заставить миксины работать с дженериками, пользовательский сеттер для the_list не вызывался, вероятно, потому, что это список, JsonCreator не вариант, так как я не писал парный класс...).


person veryltdbeard    schedule 12.12.2014    source источник


Ответы (1)


Вы должны написать собственный сериализатор/десериализатор для класса Pair.

Вот пример:

public class JacksonPair {
    static final String JSON = "{ \"x\" : 1,  \n" +
            "  \"y\" : 2, \n" +
            "  \"the_list\" : [[1,2],[3,4]]}";

    static class Demo {
        public int x;
        public int y;
        public List<Pair<Integer, Integer>> the_list;

        @Override
        public String toString() {
            return "Demo{" +
                    "x=" + x +
                    ", y=" + y +
                    ", the_list=" + the_list +
                    '}';
        }
    }

    static class PairSerializer extends JsonSerializer<Pair> {

        @Override
        public void serialize(
                Pair pair,
                JsonGenerator jsonGenerator,
                SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartArray(2);
            jsonGenerator.writeObject(pair.getLeft());
            jsonGenerator.writeObject(pair.getRight());
            jsonGenerator.writeEndArray();
        }
    }

    static class PairDeserializer extends JsonDeserializer<Pair> {

        @Override
        public Pair deserialize(
                JsonParser jsonParser,
                DeserializationContext deserializationContext) throws IOException {
            final Object[] array = jsonParser.readValueAs(Object[].class);
            return Pair.of(array[0], array[1]);
        }
    }

    public static void main(String[] args) throws IOException {
        final SimpleModule module = new SimpleModule();
        module.addSerializer(Pair.class, new PairSerializer());
        module.addDeserializer(Pair.class, new PairDeserializer());
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(module);
        final Demo demo = objectMapper.readValue(JSON, Demo.class);
        System.out.println("toString: " + demo);
        System.out.println("Input: " + JSON);
        System.out.println("Output: " + objectMapper.writeValueAsString(demo));
    }
}

Выход:

toString: Demo{x=1, y=2, the_list=[(1,2), (3,4)]}
Input: { "x" : 1,  
  "y" : 2, 
  "the_list" : [[1,2],[3,4]]}
Output: {"x":1,"y":2,"the_list":[[1,2],[3,4]]}
person Alexey Gavrilov    schedule 14.12.2014