Пользовательские Java-примитивы сериализации json от kotlin от Jackson

В моем проекте есть модули java и kotlin. В каком-то модуле kotlin мне нужна пользовательская сериализация. Все длинные значения должны быть сериализованы как строки. Я использую Джексона.

Пример:

котлин

data class KotlinRecord(val id: Long)

Джава

public class JavaRecord {
    private Long id;

    public Long getId() {
        return id;
    }

    public JavaRecord setId(Long id) {
        this.id = id;
        return this;
    }
}

Когда ObjectMapper настроен в модуле Джава, и я сериализую значение следующим образом:

 ObjectMapper mapper = new ObjectMapper()
            .registerModule(new KotlinModule())
            .registerModule(new JavaTimeModule())
            .registerModule(
                    new SimpleModule()
                            .addSerializer(Long.class, LongToStringJSONSerializer.ofObject())
                            .addSerializer(long.class, LongToStringJSONSerializer.ofPrimitive())
            );

JavaRecord javaRecord = new JavaRecord().setId(Long.MAX_VALUE);
KotlinRecord kotlinRecord = new KotlinRecord(Long.MAX_VALUE);

System.out.println("Java record:   " + mapper.writeValueAsString(javaRecord));
System.out.println("Kotlin record: " + mapper.writeValueAsString(kotlinRecord));

Я получаю следующий результат:

Java record:   {"id":"9223372036854775807"}
Kotlin record: {"id":"9223372036854775807"}

Все хорошо. Это то что мне нужно.

Но если я сделаю то же самое в модуле котлин следующим образом:

val mapper = ObjectMapper()
        .registerModule(KotlinModule())
        .registerModule(JavaTimeModule())
        .registerModule(
                SimpleModule()
                        .addSerializer(Long::class.java, LongToStringJSONSerializer.ofObject())
                        .addSerializer(Long::class.javaPrimitiveType, LongToStringJSONSerializer.ofPrimitive())
        )

val javaRecord = JavaRecord().setId(Long.MAX_VALUE)
val kotlinRecord = KotlinRecord(Long.MAX_VALUE)

println("Java record:   ${mapper.writeValueAsString(javaRecord)}")
println("Kotlin record: ${mapper.writeValueAsString(kotlinRecord)}")

Я получил:

Java record:   {"id":9223372036854775807}
Kotlin record: {"id":"9223372036854775807"}

Для записи, определенной как длинное значение класса java, не было преобразовано в строку.

Мой пользовательский сериализатор:

public class LongToStringJSONSerializer extends JsonSerializer<Long> {
    private boolean forPrimitive;

    private LongToStringJSONSerializer(boolean forPrimitive) {
        this.forPrimitive = forPrimitive;
    }

    @Override
    public void serialize(Long longVal, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws
            IOException {
        jsonGenerator.writeObject(longVal == null ? "" : String.valueOf(longVal));
    }

    @Override
    public Class<Long> handledType() {
        return forPrimitive ? long.class : Long.class;
    }

    public static LongToStringJSONSerializer ofPrimitive() {
        return new LongToStringJSONSerializer(true);
    }

    public static LongToStringJSONSerializer ofObject() {
        return new LongToStringJSONSerializer(false);
    }
} 

Может ли кто-нибудь объяснить это поведение и что нужно сделать, чтобы исправить это? Спасибо!

Похоже, проблема связана с привязкой, в частности здесь: Long::class.javaPrimitiveType Я предполагаю, что это неупакованный тип в Java. Это не то, что Long в Java.

cmaynard 03.06.2019 15:24

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

V. Kuznetsov 03.06.2019 15:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
2
1 981
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема была в неправильном типе сериализации.

Преобразователь объектов должен быть определен следующим образом:

val mapper = ObjectMapper()
        .registerModule(KotlinModule())
        .registerModule(JavaTimeModule())
        .registerModule(
                SimpleModule()
                        .addSerializer(Long::class.javaPrimitiveType, LongToStringJSONSerializer.ofObject())
                        .addSerializer(Long::class.javaObjectType, LongToStringJSONSerializer.ofPrimitive())
        )

Я пропустил Long::class.javaObjectType

Другие вопросы по теме