Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson: "Unexpected token (VALUE_STRING), expected FIELD_NAME:" when deserializing empty string instead of expected object

I'm using Jackson to deserialize json responses from a server I do not own. I'm using JsonTypeInfo annotations to handle polymorphic data types. Here's the configuration I have on my base type (Thing in this case):

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Thing.class, name = "Thing"),
        @JsonSubTypes.Type(value = FancyThing.class, name = "FancyThing")
})

Everything works great until the server returns an empty string where I am expecting one of these types and then I get one of these:

org.codehaus.jackson.map.JsonMappingException: Unexpected token (VALUE_STRING), expected FIELD_NAME: missing property 'type' that is to contain type id (for class com.stackoverflow.Thing)

Is there a recommended way of handling cases like this? Like I said, I don't control the server, so I have to handle this client side. I'd rather handle this by configuring the ObjectMapper, but ObjectMapper#configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true) doesn't seem to work the way I had expected. Any ideas?

like image 992
CtrlF Avatar asked Mar 22 '23 19:03

CtrlF


1 Answers

Ok, so sometimes all it takes to get an answer is to ask yourself the right question. It turns out, I think I was looking at an older version of the javadocs, because I discovered @JsonTypeInfo#defaultImpl and that has set me on to the right track.

Now I have something that looks like this:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type"
        defaultImpl = EmptyThing.class)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Thing.class, name = "Thing"),
        @JsonSubTypes.Type(value = FancyThing.class, name = "FancyThing")
})
public class Thing {

...

}

public class EmptyThing extends Thing {

    public EmptyThing(String s) {
        // Jackson wants a single-string constructor for the default impl
    }
}
like image 185
CtrlF Avatar answered Mar 24 '23 08:03

CtrlF