Пара Java Apache сериализуется в одном формате и десериализуется в другом формате с использованием Jackson Serialize

#java #json #apache #rest #jackson

#java #json #апач #остальное #джексон #apache

Вопрос:

При сериализации Apache Mutable Pair с помощью Jackson @JsonSerialize аннотации создается такая структура

 {"leftValue": "rightValue"}
  

но для обработки во время десериализации с использованием Jackson @JsonDeserialize аннотации ожидается такая структура

 {
"left":"leftValue",
"right": "rightValue"
}
  

Такие методы, как getLeft() or getValue() , возвращают null при использовании первой структуры, но возвращают правильные значения в случае второй структуры.

Как это может быть сериализовано во вторую структуру? Также какая структура рекомендуется?

Ответ №1:

org.apache.commons.lang3.tuple.MutablePair расширяет, Pair который реализует Map.Entry интерфейс. Map.Entry по умолчанию обрабатывается Jackson как Map объект, который сериализуется в JSON как key-value структура. Чтобы сериализовать ее как классическую POJO , нам нужно реализовать пользовательский сериализатор, который определит правильную структуру:

 class MutablePairJsonSerializer extends JsonSerializer<MutablePair> {

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

Простое приложение, которое использует вышеупомянутый сериализатор:

 import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.commons.lang3.tuple.MutablePair;

import java.io.IOException;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        MutablePair<String, String> pair = new MutablePair<>();
        pair.setLeft("leftV");
        pair.setRight("rightV");

        SimpleModule pairModule = new SimpleModule();
        pairModule.addSerializer(MutablePair.class, new MutablePairJsonSerializer());

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(pairModule);

        String json = mapper.writeValueAsString(pair);
        System.out.println(json);
        System.out.println(mapper.readValue(json, MutablePair.class));
    }
}
  

С принтами:

 {
  "left" : "leftV",
  "right" : "rightV"
}
(leftV,rightV)
  

Который показывает, что объект сериализуется с помощью ключей и десериализуется должным образом для object.

Если мы хотим сохранить процесс сериализации по умолчанию, нам нужно настроить десериализатор, который может выглядеть следующим образом:

 import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.commons.lang3.tuple.MutablePair;

import java.io.IOException;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        MutablePair<String, String> pair = new MutablePair<>();
        pair.setLeft("leftV");
        pair.setRight("rightV");

        SimpleModule pairModule = new SimpleModule();
        pairModule.addDeserializer(MutablePair.class, new MutablePairJsonDeserializer());

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(pairModule);

        String json = mapper.writeValueAsString(pair);
        System.out.println(json);
        System.out.println(mapper.readValue(json, MutablePair.class));
    }
}

class MutablePairJsonDeserializer extends JsonDeserializer<MutablePair> {

    @Override
    public MutablePair deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        p.nextToken(); // SKIP START_OBJECT
        String keyName = p.getCurrentName();
        p.nextToken();

        return MutablePair.of(keyName, p.getValueAsString());
    }
}