FasterXML / jackson-annotations

Core annotations (annotations that only depend on jackson-core) for Jackson data processor
https://github.com/FasterXML/jackson
Apache License 2.0
1.03k stars 330 forks source link

Nested Subtype Wrapping #126

Closed sschepens closed 6 years ago

sschepens commented 6 years ago

I'm trying to serialize the following structure. Classes:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.WRAPPER_OBJECT,
        property = "type"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = MyChildContainer1.class, name = "container_1"),
        @JsonSubTypes.Type(value = MyChildContainer2.class, name = "container_2"),
        @JsonSubTypes.Type(value = MyChild.class, name = "my_child"),
})
public abstract class MyClass {
}

public class MyChildContainer1 extends MyClass {
    public MyClass myClass;

    @JsonValue
    public MyClass getMyClass() {
        return myClass;
    }
}

public class MyChildContainer2 extends MyClass {
    public MyClass myClass;

    @JsonValue
    public MyClass getMyClass() {
        return myClass;
    }
}

public class MyChild extends MyClass {
    public String field;
}

Test case:

        MyChildContainer1 myChild1 = new MyChildContainer1();
        MyChildContainer2 myChild2 = new MyChildContainer2();
        MyChild myChild3 = new MyChild();
        myChild3.field = "field";

        myChild2.myClass = myChild3;
        myChild1.myClass = myChild2;
        System.out.println(JsonUtils.INSTANCE.toJsonString(myChild1));

I would expect this test to print

{"container_1":{"container_2":{"my_child":{"field":"field"}}}}

But instead it outputs

{"container_1":{"field":"field"}}

It seems to be ignoring wrapping because i'm using @JsonValue, what's strange is that deserializing the content I expected works. Am I doing this wrong? Is there other way I can achieve this?

cowtowncoder commented 6 years ago

First of all this problem should be reported against jackson-databind, as this package only defines annotations but does not contain code to use them (databind does). Second: it would be good to know which version of Jackson you are using.

Other than this, combination of @JsonValue and polymorphic types is problematic from implementation perspective -- in this case I am not sure how deserialization could work (for example), there not being matching @JsonCreator. I can't say for sure whether handling for serialization is correct or not without investigating it, but I would strongly recommend trying to solve your use case without use of @JsonValue.

sschepens commented 6 years ago

@cowtowncoder I'm gonna reopen this against jackson-databind.

I forgot to add constructors with @JsonCreator, but yes, adding those constructors makes deserialization work.

How can I avoid using @JsonValue, I seem to need to have those container classes, but serialize it as and internal property.