Skip to content

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

Description

@naxostech

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working right

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions