Custom json serialization java primitives from kotlin by Jackson

V. Kuznetsov :

In my project there are java and kotlin modules. In some kotlin module I need a custom serialization. All long values should be serialized as string. I use Jackson.

Example:

kotlin

data class KotlinRecord(val id: Long)

java

public class JavaRecord {
    private Long id;

    public Long getId() {
        return id;
    }

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

When ObjectMapper is configured in java module and I serialize value like this:

 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));

I get the following result:

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

It's fine. That's what i need.

But if I do the same in kotlin module like this:

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)}")

I get:

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

For record defined as java class long value wasn't conveted to string.

My custom serializer:

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);
    }
} 

Can anyone explain this behavior and what needs to be done to fix it? Thanks!

V. Kuznetsov :

Problem was in the wrong type of serialization.

Object mapper should be defined like this:

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

I missed Long::class.javaObjectType

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=132306&siteId=1