Jackson-databind: @JsonTypeInfo visible=true serialises the field twice

Created on 16 Jul 2013  路  15Comments  路  Source: FasterXML/jackson-databind

Spun off from #250.

The below code will add a name field twice into the serialised JSON:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "name", visible = true)
public static abstract class Fruit {
    // @JsonIgnore
    public abstract String getName();
}

Adding in the @JsonIgnore is a workaround but I cannot imagine a circumstance where I would want that behaviour. This ticket is requesting a "visible" property be ignored by default during serialisation.

Most helpful comment

Oh. How quickly do I forget features I add. The REAL answer is that there is specific annotation -- @JsonTypeId -- to be used to indicate property that gives type id value. Its name may be same as specified by propertyName, but need not be; similarly, this id may be used with any inclusion methods (as-wrapper-array, as-wrapper-object, external-property).

All 15 comments

Hitting this issue too. I had to @JsonIgnore the field and the getter to implement the workaround... it took me a while to figure that out :angry:

Hmmh. Ok, this is odd: handling of 'visible' should specifically make things work such that existing accessor (getter) would be used only; and no generation should occur. This as per [http://jira.codehaus.org/browse/JACKSON-762].

I'll see what gives.

Oh. How quickly do I forget features I add. The REAL answer is that there is specific annotation -- @JsonTypeId -- to be used to indicate property that gives type id value. Its name may be same as specified by propertyName, but need not be; similarly, this id may be used with any inclusion methods (as-wrapper-array, as-wrapper-object, external-property).

Ok, so the current idea (wrt existing code) is that instead of @JsonIgnore, you should use @JsonTypeId. Whether you want visible=true or not depends on what you are trying to achieve: it is only needed if you have a matching setter.
Setting of visible does not actually come into play here; rather it is just missing linkage between type id (which happens to be marked to be added as 'name') and regular property.

Still... it seems odd to add duplicate entries regardless. Question then becomes: which mechanism should be used for figuring out type id to use? If @JsonTypeId is used, answer seems clear: use the property (via getter or field access). Without it, it seems logical that type id should be generated instead.

I will try to see how to do such supression. Please let me know if I misunderstood anything from above.

Thanks for your response. I wasn't aware of @JsonTypeId. I was setting visible = true so that the property would be set.

I'd say the documentation could be a little clearer. Here's the Javadoc for the visible property:

Property that defines whether type identifier value will be passed as part of JSON stream to deserializer (true), or handled and removed by TypeDeserializer (false).

It doesn't mention anything about serialization!

In the end I implemented custom @JsonTypeResolver and @JsonTypeIdResolver to work around other issues I was having, which made the @JsonIgnore workaround unnecessary.

Question then becomes: which mechanism should be used for figuring out type id to use?

@JsonTypeId seems like a perfectly reasonable solution, but ideally it could be clearer in the documentation that this exists.

However, there is always the possibility of accidental API misuse and ideally it should throw an Exception rather than serializing duplicate properties. Not sure how easy that would be to implement, though.

I'm using Jackson 2.1.4 so I apologize if any of the above is out-of-date.

Documentation is incomplete and misleading, yes. I will update it for 2.3.0.

I will also consider implementing "EXISTING_PROPERTY" from #250, since that could resolve another smaller issue (how to allow ordering of type id, so it doesn't have to be first item). And finally, try to suppress duplicate property, even if all else fails.

Sounds good :+1:

I met a tricky one, when I use the @JsonTypeId on my filed, it will not give me the duplicated key error, but if the type was not nested in another type, then even if I set the visible=true, my field was a null in the output json, anyone has any idea?

@JakimLi Please open a new issue; adding related but different problems in existing issues makes it more difficult to keep track of state of things.

Since #528 will track implementation fo EXISTING_PROPERTY, will close this until that gets implemented as it should solve some or all of the issues. And dealing with remaining problems (if any) can and should be started from existing state at that point.

I am having similar issue, not able to avoid or ignore field 'type' being serialized twice

I end up getting response like { "type":"test", "@type":"test"}

I need to avoid @type completely

@JsonIgnore
@JsonTypeId
private String type;

@JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, visible=true,defaultImpl=TestRO.class)
private AbstractConfigRO xmlConfig;

@JsonIgnore
public String getType() {
return type;
}

@JsonIgnore
public void setType(String type) {
this.type = type;
}

Names "type" and "@type" are different from JSON perspective. But you should be able to specify

@JsonTypeInfo(.... property="type")

to change the default of "@type" into "type".

Is there any way to do not deserialise the type information at all?

I don't want to emit the 'type' in the json, but I need polymorphism. Any workaround?

Thanks.

@aterreno so how would you figure out intended type?

I am trying to model a json that looks like this:

"relationships": { "author": { "links": { "self": "http://example.com/articles/1/relationships/author", "related": "http://example.com/articles/1/author" }, "data": { "type": "people", "id": "9" } }, "comments": { "links": { "self": "http://example.com/articles/1/relationships/comments", "related": "http://example.com/articles/1/comments" }, "data": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] }

(from http://jsonapi.org/ )

The type is in the key, not as an attribute (inside relationships), while specifying the type inside the data attribute is totally fine.

Was this page helpful?
0 / 5 - 0 ratings