Skip to content

Default subtype in @JsonbTypeInfo (for polymorphism deserialization) #368

@jmini

Description

@jmini

With @JsonbTypeInfo and @JsonbSubtype it is possible to implement polymorphism on deserialization.

But sometimes (especially in the case of the evolution of a REST API over time) the attribute corresponding to the defined key might not be present in the provided JSON message.

For this use-case, being able to specify the "default subtype" would be necessary.

Currently yasson is failing with this error:

jakarta.json.bind.JsonbException: Cannot infer a type for unmarshalling into: snippet.Snippet$Animal

Complete example:

import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
import jakarta.json.bind.annotation.JsonbSubtype;
import jakarta.json.bind.annotation.JsonbTypeInfo;

public class Snippet {

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

        @Override
        public String toString() {
            return "Dog [isDog=" + isDog + "]";
        }
    }

    public static final class Cat implements Animal {
        public boolean isCat = true;

        @Override
        public String toString() {
            return "Cat [isCat=" + isCat + "]";
        }
    }

    public static void main(String[] args) {
        // Create a Jsonb instance
        Jsonb jsonb = JsonbBuilder.create();

        // Create instances of Dog and Cat
        Dog myDog = new Dog();
        Cat myCat = new Cat();

        // Serialize Dog instance to JSON
        try {
            String dogJson = jsonb.toJson(myDog);
            System.out.println("Serialized Dog JSON: " + dogJson);

            // Serialize Cat instance to JSON
            String catJson = jsonb.toJson(myCat);
            System.out.println("Serialized Cat JSON: " + catJson);

            // Deserialize JSON (polymorphic deserialization) Dog
            Animal deserializedAnimalFromDogJson = jsonb.fromJson("{\"@type\":\"dog\"}", Animal.class);
            System.out.println("Deserialized Dog: " + deserializedAnimalFromDogJson);
            System.out.println("Deserialized Animal from Dog (instance of check): " + (deserializedAnimalFromDogJson instanceof Dog));

            // Deserialize JSON (polymorphic deserialization) Cat
            Animal deserializedAnimalFromCatJson = jsonb.fromJson("{\"@type\":\"cat\"}", Animal.class);
            System.out.println("Deserialized Cat: " + deserializedAnimalFromCatJson);
            System.out.println("Deserialized Animal from Cat (instance of check): " + (deserializedAnimalFromCatJson instanceof Cat));

            // Deserialize JSON (default impl)
            Animal a = jsonb.fromJson("{}", Animal.class);
            System.out.println("Deserialized Animal: " + a);

        } catch (JsonbException e) {
            e.printStackTrace();
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions