Джексон - изменить имя ключа карты без специального сериализатора - PullRequest
0 голосов
/ 29 июня 2018

При сериализации класса Person с использованием Джексона, где Person:

public class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "My name is "+name+" ("+age+")";
    }

}

Я получаю следующий вывод:

Map<Person, String> map = new HashMap<>();
Person john = new Person("John", 20);
map.put(john, "abc");

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(System.out, map); //1
objectMapper.writeValue(System.out, john); //2

1

{"My name is John (20)":"abc"}

2

{"name":"John","age":20}

Есть ли простой способ ( без настраиваемого сериализатора ) изменить ключ карты для использования атрибута name вместо вывода toString в # 1, не теряя выход сериализации Person объект в # 2, и без изменения возвращаемого значения toString? Я ожидаю, что есть аннотация для getName, которая делает это, но не может найти ее.

1 Ответ

0 голосов
/ 29 июня 2018

Пользовательский сериализатор и addKeySerializer, похоже, являются лучшим подходом, хотя создание модуля, добавление Serializer или KeySerializer и его регистрация с помощью картографов несколько сложнее.

Если по какой-либо причине (как вы заявили) вы не можете использовать собственный сериализатор. Ниже приведено несколько вариантов, которые могут вам помочь

Оба выдают результат

{"John":"abc"}

При написании карты, но оставить один объект без изменений

{"name":"John","age":20}

Потоки Java 8 для отображения на выходе

В зависимости от того, насколько сложны ваши реальные объекты, по сравнению с простым примером вы можете просто сделать отображение во время или перед вызовом writeValue.

    mapper.writeValue(System.out,
                      map.entrySet().stream().collect(
                         Collectors.toConcurrentMap(
                            k -> k.getKey().getName(),
                            Function.identity())));

Реализация JsonSerializable в коллекции

Если вы можете изменить свою коллекцию на пользовательскую версию, которая расширяет HashMap.

class PersonHashMap extends HashMap<Person, String> implements JsonSerializable {

    @Override
    public void serialize(JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        for (Entry<Person, String> e : entrySet()) {
            jsonGenerator.writeStringField(e.getKey().getName(), e.getValue());
        }
        jsonGenerator.writeEndObject();
    }

    @Override
    public void serializeWithType(JsonGenerator jsonGenerator, SerializerProvider serializerProvider, TypeSerializer typeSerializer) throws IOException {
        .
        .
        .
    }
}

Недостаток в том, что вам нужно было бы контролировать инициализацию карты, чтобы сделать что-то вроде этого:

Map<Person, String> map = new PersonHashMap();

Но опять же, это все, что нужно, без дополнительного модуля или регистрации в вашем объектном картографическом устройстве, как если бы вы делали это с JsonSerializer.

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