vavr-io / vavr-jackson

Jackson datatype module for Vavr
Apache License 2.0
97 stars 35 forks source link

Serialising Either: IncompatibleClassChangeError #174

Open mcac0006 opened 3 years ago

mcac0006 commented 3 years ago
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new VavrModule());

// yields [1]
System.out.println(objectMapper.writeValueAsString(List.of(1)));

final Cat cat = new Cat();
cat.name = "Bianca";
final Either<Cat, Dog> either = Either.left(cat);

// yields java.lang.IncompatibleClassChangeError: Found class io.vavr.control.Either, but interface was expected
System.out.println(objectMapper.writeValueAsString(either));

Some observations:

mincong-h commented 3 years ago

Hi @mcac0006 , thanks for reporting this. It sounds like a bug. On my side, I tried to reproduce it but without success. Could you provide more detail, such as the version of Vavr-Jackson, the version of Jackson, the source code of Cat and Dog?

Here is the my attempt but both tests passed, using the last commit 0538bdb4bc107537ef7c8a2aaa5c3880588ab725 on master branch:

package io.vavr.jackson.issues;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vavr.control.Either;
import io.vavr.jackson.datatype.VavrModule;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class Issue174Test {
    @Test
    void eitherLeft() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new VavrModule());
        Cat cat = new Cat();
        cat.name = "Bianca";
        Either<Cat, Dog> either = Either.left(cat);

        String json = objectMapper.writeValueAsString(either);
        assertEquals("[\"left\",{\"name\":\"Bianca\"}]", json);

        Either<Cat, Dog> restored = objectMapper.readValue(json, new TypeReference<Either<Cat, Dog>>() {});
        assertEquals("Bianca", restored.getLeft().name);
    }

    @Test
    void eitherRight() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new VavrModule());

        Dog dog = new Dog();
        dog.name = "Labrador";
        Either<Cat, Dog> either = Either.right(dog);

        String json = objectMapper.writeValueAsString(either);
        assertEquals("[\"right\",{\"name\":\"Labrador\"}]", json);

        Either<Cat, Dog> restored = objectMapper.readValue(json, new TypeReference<Either<Cat, Dog>>() {});
        assertEquals("Labrador", restored.get().name);
    }

    static class Cat {
        @JsonProperty("name")
        String name;
    }

    static class Dog {
        @JsonProperty("name")
        String name;
    }
}