В моем проекте есть модули 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);
}
}
Может ли кто-нибудь объяснить это поведение и что нужно сделать, чтобы исправить это? Спасибо!
Если я использую примитивное длинное значение в классе java, я получаю ожидаемый результат. Проблема только с типом объекта Long.




Проблема была в неправильном типе сериализации.
Преобразователь объектов должен быть определен следующим образом:
val mapper = ObjectMapper()
.registerModule(KotlinModule())
.registerModule(JavaTimeModule())
.registerModule(
SimpleModule()
.addSerializer(Long::class.javaPrimitiveType, LongToStringJSONSerializer.ofObject())
.addSerializer(Long::class.javaObjectType, LongToStringJSONSerializer.ofPrimitive())
)
Я пропустил Long::class.javaObjectType
Похоже, проблема связана с привязкой, в частности здесь:
Long::class.javaPrimitiveTypeЯ предполагаю, что это неупакованный тип в Java. Это не то, чтоLongв Java.