yasson icon indicating copy to clipboard operation
yasson copied to clipboard

The example for jakarta.json.bind.annotation.JsonbSubtype is misleading

Open naxostech opened this issue 11 months ago • 1 comments

Hello. I use Yasson 3.0.4 with OpenJDK (Temurin) 21.0.5 and Windows 11.

At first, the example for jakarta.json.bind.annotation.JsonbSubtype contains several trivial compile errors that should be fixed even though the purpose isn't to provide a fully working example:

  • a comma is missing after the declaration of the first JsonbSubtype annotation
  • isDog, isCat and isRat are wrongly declared as String whereas the rest of the source code expects to manipulate booleans

Secondly, the example demonstrates the serialization but not the deserialization.

Thirdly, the deserialization doesn't work as is when fixing the trivial compile errors mentioned earlier except if the interface and the classes are either saved into separate source files or declared static into the same source file: jakarta.json.bind.JsonbException: Cannot create instance of a class: class Cat, No default constructor found. at org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.(DefaultObjectInstanceCreator.java:44) at org.eclipse.yasson.internal.deserializer.DeserializationModelCreator.createObjectDeserializer(DeserializationModelCreator.java:251) at org.eclipse.yasson.internal.deserializer.DeserializationModelCreator.deserializerChainInternal(DeserializationModelCreator.java:193) at org.eclipse.yasson.internal.deserializer.DeserializationModelCreator.deserializerChain(DeserializationModelCreator.java:135) at org.eclipse.yasson.internal.deserializer.DeserializationModelCreator.deserializerChain(DeserializationModelCreator.java:123) at org.eclipse.yasson.internal.deserializer.InheritanceInstanceCreator.deserialize(InheritanceInstanceCreator.java:71) at org.eclipse.yasson.internal.deserializer.InheritanceInstanceCreator.deserialize(InheritanceInstanceCreator.java:31) at org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:85) at org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:34) at org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:46) at org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:26) at org.eclipse.yasson.internal.DeserializationContextImpl.deserializeItem(DeserializationContextImpl.java:138) at org.eclipse.yasson.internal.DeserializationContextImpl.deserialize(DeserializationContextImpl.java:127) at org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:55) at org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:62)

Please find below the minimal changes I suggest for the example:

// Example
// Animal.java
 @JsonbTypeInfo({
      @JsonbSubtype(alias = "dog", type = Dog.class),
      @JsonbSubtype(alias = "cat", type = Cat.class)
 })
 interface Animal {}

// Dog.java
 class Dog implements Animal {
     public boolean isDog = true;
 }
// Cat.java
 class Cat implements Animal {
     public boolean isCat = true;
 }
// Rat.java
 class Rat implements Animal {
     public boolean isRat = true;
 }

 jsonb.toJson(new Dog());// {"@type":"dog","isDog":true}
 jsonb.toJson(new Cat());// {"@type":"cat","isCat":true}
 jsonb.toJson(new Rat());// {"isRat":true}
 jsonb.fromJson("{\"@type\":\"cat\",\"isCat\":true}", Animal.class);// Cat@...

Please find below my fully working example:

public class Main {
    @JsonbTypeInfo({
        @JsonbSubtype(alias = "dog", type = Dog.class),
        @JsonbSubtype(alias = "cat", type = Cat.class)
    })
    public static interface Animal {
    }

    public static final class Dog implements Animal {

        public boolean isDog = true;
    }

    public static final class Cat implements Animal {

        public boolean isCat = true;
    }

    public static final class Rat implements Animal {

        public boolean isRat = true;
    }

    public static void main(final String[] args) throws Exception {
        try (final Jsonb jsonb = JsonbBuilder.create()) {
            System.out.println(jsonb.toJson(new Dog()));
            System.out.println(jsonb.toJson(new Cat()));
            System.out.println(jsonb.toJson(new Rat()));
            System.out.println(jsonb.fromJson("{\"@type\":\"cat\",\"isCat\":true}", Animal.class));
        }
    }
}

Feel free to move this issue upstream if it makes sense for you.

naxostech avatar Feb 03 '25 09:02 naxostech

@naxostech can you give a link where you see the wrong example?

jmini avatar Mar 19 '25 13:03 jmini