Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jackson does not include type info in fields #1015

Closed
akshay-sharma opened this issue Nov 21, 2015 · 5 comments
Closed

Jackson does not include type info in fields #1015

akshay-sharma opened this issue Nov 21, 2015 · 5 comments

Comments

@akshay-sharma
Copy link

I am trying to serialize an object to json using jackson 2.6.3 I want to include type info in the serialized json. This does not work for members nested within this class.

Here is the test code.

public class Test {

@JsonSubTypes({ @JsonSubTypes.Type(value = ConcreteA.class)})
interface A {
}

@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS)
class ConcreteA implements A {
}

@JsonSubTypes({ @JsonSubTypes.Type(value = ConcreteB.class)})
interface B {
}

@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS)
class ConcreteB implements B {
    A a;
    public A getA() {
        return a=new ConcreteA();
    }
}

@org.junit.Test
public void testSerialisation() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    System.out.println(objectMapper.writeValueAsString(new ConcreteB()));
}
}

The json being converted by jackson is

{"@class":"Test$ConcreteB","a":{}}

Note that it does not include type info for field 'a'. The type info does get included while serializing just A.

{"@class":"Test$ConcreteA"} 
@cowtowncoder
Copy link
Member

The problem here is that @JsonTypeInfo really has to be put in a common supertype, and should not be used in subtypes. It is not enough that values are of implementation types that have that annotation: it must be placed so it is visible from the declared (static) type. In this case it means that field a is only known to be of type A, and that type does not have necessary annotations to indicate type information is needed. Handling this way is done primarily because during deserialization only static type information is available (so deserialization would fail).

So: to solve the problem, you would need to move @JsonTypeInfo either on interface A, or on property a.

@akshay-sharma
Copy link
Author

Putting jsonTypeInfo to just interfaces serializes it as :

{"@class":"Test$ConcreteB","a":{"@class":"Test$A"}}

Notice that is marks the @Class value as interface type A.

However, strangely, A alone gets serialized properly

A a  = new ConcreteA();
System.out.println(objectMapper.writeValueAsString(a));

as

{"@class":"Test$ConcreteA"}

I want to serialize and then deserialize objects which will hold different implementations of an interface. Thus concrete type info would be required for deserialization.(And hopefully can be used for deserialization)

@david-bakin
Copy link

Have you tried using @JsonTypeInfo (instead of @JsonSubTypes) as described here? (And also here, which is where I struggled with understanding what Jackson calls "polymorphic deserialization").

@cowtowncoder
Copy link
Member

@akshay-sharma This is not enough to help: please include relevant class/interface definitions.

@akshay-sharma
Copy link
Author

It looks like I was facing problems due to innner classes I wrote for testing. I put public and static qualifier on these and are able to get the desired behavior now.

Here is the modified test I began with case http://pastebin.com/4g84rsAd
Here is a better verbose test case http://pastebin.com/7kJcWfsH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants