Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore Jackson polymorphic type mapping

Tags:

jackson

I'm using @JsonTypeInfo and @JsonSubTypes to map parsing subclasses based on a given property. Here's a contrived example of my sample JSON that I want to parse.

{ "animals": [
      { "type" : "dog", "name" : "spike" }
     ,{ "type" : "cat", "name" : "fluffy" }
]}

Using this as the class

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME
             ,include = JsonTypeInfo.As.PROPERTY
             ,property = "type")  
@JsonSubTypes({  
   @Type(value = Cat.class, name = "cat"),  
   @Type(value = Dog.class, name = "dog") })  
abstract class Animal  {
  public String name;
{ 

class Dog extends Animal  {  }  
class Cat extends Animal  {  } 

However, the problem occurs when the JSON contains type that I would want to ignore. For example, if I have a new type "pig" that I don't really want to deserialize as an object:

{ "animals": [
      { "type" : "dog", "name" : "spike" }
     ,{ "type" : "cat", "name" : "fluffy" }
     ,{ "type" : "pig", "name" : "babe" }
]}

and try to parse it, it will give me this error:

Could not resolve type id 'pig' into a subtype of [simple type, class Animal]

How can I fix it so that I can map only those animals of type 'dog' and 'cat', and ignore everything else?

like image 355
geofrey Avatar asked Jul 02 '14 18:07

geofrey


Video Answer


1 Answers

You can avoid exception by setting the JsonTypeInfo.defaultImpl annotation attibute to java.lang.Void or NoClass depending on the Jackson version you are using.

Here is an example:

public class JacksonUnknownType {
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY,
            property = "type", defaultImpl = Void.class)
    @JsonSubTypes({
            @JsonSubTypes.Type(value = Cat.class, name = "cat"),
            @JsonSubTypes.Type(value = Dog.class, name = "dog")})
    public abstract static class Animal {
        public String name;
        @Override
        public String toString() {
            return getClass().getName() + " :: " + name;
        }
    }

    public static class Dog extends Animal {
    }

    public static class Cat extends Animal {
    }

    public static final String JSON = "[\n" +
            "      { \"type\" : \"dog\", \"name\" : \"spike\" }\n" +
            "     ,{ \"type\" : \"cat\", \"name\" : \"fluffy\" }\n" +
            "     ,{ \"type\" : \"pig\", \"name\" : \"babe\" }\n" +
            "]";

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        List<Animal> value = mapper.readValue(JSON, new TypeReference<List<Animal>>() {});
        System.out.println(value);
    }

}

Output:

[stackoverflow.JacksonUnknownType$Dog :: spike, stackoverflow.JacksonUnknownType$Cat :: fluffy, null, null, null]

Note that the resulting collection contains 3 null items instead of 1. This may be a bug in Jackson but it is easy to tolerate.

like image 169
Alexey Gavrilov Avatar answered Sep 28 '22 03:09

Alexey Gavrilov