Сериализатор Jackson выдает недопустимый Json для подкласса Map

#java #json #jackson

#java #json #джексон

Вопрос:

У меня есть этот фрагмент кода, который сериализует подкласс Map с использованием Jackson. Без зарегистрированного сериализатора я получаю действительный json, я использую сериализатор, чтобы перевести имя в нижний регистр. Однако созданный json выглядит так:

 {:"two":"aaa":"one":"aaa"}
 

Есть идеи, почему? Как исправить?

 @Test
public void test_serialization() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule("JSONModule", new Version(1, 0, 0, null, null, null));
    module.addSerializer(Circle.class, new CircleSerializer());
    module.addKeySerializer(Circle.class, new CircleSerializer());
    mapper.registerModule(module);

    CircleMap statistics = new CircleMap();
    statistics.put(Circle.ONE, "aaa");
    statistics.put(Circle.TWO, "aaa");

    System.out.println(mapper.writeValueAsString(statistics));
}

enum Circle {
    ONE, TWO
}

static class CircleMap extends HashMap<Circle, String> {
}

static class CircleSerializer extends JsonSerializer<Circle> {
    @Override
    public void serialize(Circle value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {
        gen.writeString(value.name().toLowerCase());
    }
}
 

Комментарии:

1. Прокомментируйте свою module.addKeySerializer реплику, и она должна сработать.

2. Я не думаю, что это заслуживает понижения. Это был полностью рабочий пример, демонстрирующий проблему.

Ответ №1:

Заменить

 gen.writeString(value.name().toLowerCase());
 

с

 gen.writeFieldName(value.name().toLowerCase());
 

Вы сериализуете ключ. Это интерпретируется как имя поля JSON, поэтому вы должны использовать этот метод. writeString государства javadoc

Способ вывода строкового значения. В зависимости от контекста это означает либо элемент массива, либо значение поля (объекта), либо отдельную строку;

Вы прямо пишете строковое значение. Это не то, что вы хотите.

Обратите внимание, что вам понадобится другой сериализатор для ключей и для обычных значений.