Пользовательские сериализаторы Джексона - PullRequest
1 голос
/ 01 октября 2019

Может ли отдельный настраиваемый сериализатор использоваться в качестве сериализатора ключей и обычного сериализатора объектов?

, т. Е. Когда-нибудь использовать сериализатор в качестве сериализатора ключей для сериализации ключей карты, а в другое время - обычную сериализацию объекта.

У меня возникли проблемы с объектом JsonGenerator, переданным методу сериализатора.

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

1 Ответ

1 голос
/ 01 октября 2019

Вы можете использовать тот же пользовательский сериализатор, но вам нужно как-то различать, нужно ли вам генерировать свойство или весь объект. Map сериализуется в JSON Object, где Map ключи преобразуются в JSON Object свойства. Для генерации свойства с Jackson нам нужно использовать метод writeFieldName. Чтобы отличить, как вы хотите использовать этот сериализатор в конструкторе, вы можете предоставить эту информацию. Пример:

import com.fasterxml.jackson.core.JsonGenerator;
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 java.io.IOException;
import java.util.Collections;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        SimpleModule userModule = new SimpleModule();
        userModule.addSerializer(User.class, new UserJsonSerializer(false));
        userModule.addKeySerializer(User.class, new UserJsonSerializer(true));

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

        User user = new User();
        System.out.println(mapper.writeValueAsString(Collections.singletonMap(user, user)));
    }
}

class User {

    private String firstName = "Tom";
    private String lastName = "Smith";

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

class UserJsonSerializer extends JsonSerializer<User> {

    private final boolean generateKey;

    UserJsonSerializer(boolean generateKey) {
        this.generateKey = generateKey;
    }

    @Override
    public void serialize(User value, JsonGenerator gen, SerializerProvider serializers)
        throws IOException {
        if (generateKey) {
            serializeAsMapKey(value, gen);
        } else {
            serializeAsObject(value, gen);
        }
    }

    private void serializeAsMapKey(User value, JsonGenerator gen) throws IOException {
        gen.writeFieldName(String.join(",", value.getFirstName(), value.getLastName()));
    }

    private void serializeAsObject(User value, JsonGenerator gen) throws IOException {
        gen.writeStartObject();
        gen.writeFieldName("first");
        gen.writeString(value.getFirstName());
        gen.writeFieldName("last");
        gen.writeString(value.getLastName());
        gen.writeEndObject();
    }
}

Над отпечатками кода:

{
  "Tom,Smith" : {
    "first" : "Tom",
    "last" : "Smith"
  }
}

Если у вас нет общей логики, вы можете просто создать два отдельных класса: UserJsonSerializer и UserKeyJsonSerializer, который являетсяобъектно-ориентированное и понятное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...