title: Jackson JSON, Immutable Classes, and Interfaces
body: <p>I am playing with the Jackson examples and am having some trouble getting deserialization to work with immutable classes and interfaces.</p>
  
  <p>Below is my code:</p>
  
  <pre><code>package com.art.starter.jackson_starter;
  
  import java.io.IOException;
  import java.io.StringReader;
  import java.io.StringWriter;
  
  import org.codehaus.jackson.JsonGenerationException;
  import org.codehaus.jackson.map.JsonMappingException;
  import org.codehaus.jackson.map.ObjectMapper;
  /**  * Hello world!  *  */ public class App  {
      public static void main( String[] args ) throws JsonGenerationException, JsonMappingException, IOException
      {
          System.out.println( "Hello World!" );
  
          AddressImpl.AddressBuilder builder = new AddressImpl.AddressBuilder();
          NameImpl.Builder nameBuilder = new NameImpl.Builder();
          UserImpl.Builder userBuilder = new UserImpl.Builder();
  
  
          Name name = nameBuilder.first("FirstName")
                    .last("LastName")
                    .build();
  
          Address address =  builder.setCity("TestCity")
                 .setCountry("TestCountry")
                 .setState("PA")
                 .setStreet("TestAddress")
                 .setZip(123)
                 .build();      
  
          User user = userBuilder.address(address)
                   .gender(User.Gender.MALE)
                   .isVerified(true)
                   .userImage(new byte[5])
                   .build();
  
          System.out.println(address);        
          System.out.println(name);
          System.out.println(user);
  
          StringWriter sw = new StringWriter();
          ObjectMapper mapper = new ObjectMapper();
          mapper.writeValue(sw, user);
          System.out.println(sw);
  
  
         StringReader sr = new StringReader("{\"address\":{\"state\":\"PA\",\"country\":\"TestCountry\",\"street\":\"TestAddress\",\"city\":\"TestCity\",\"zip\":123},\"verified\":true,\"gender\":\"MALE\",\"userImage\":\"AAAAAAA=\"}");
  
         /* 
            This line throws the Exception           
         */
         User user2 = mapper.readValue(sr, UserImpl.class);
  
         System.out.println(user2);
      } }
  
  package com.art.starter.jackson_starter;
  
  import java.util.Arrays;
  
  import org.codehaus.jackson.annotate.JsonCreator;
  import org.codehaus.jackson.annotate.JsonProperty;
  
  public final class UserImpl implements User
  {
     private final Address address;
     private final Gender gender;
     private final byte[] userImage;
     private final boolean isVerified;
  
     public static class Builder
     {
        private Address address;
        private Gender gender;
        //      private Name name;
        private byte[] userImage;
        private boolean isVerified;
  
        public Builder address(Address address)
        {
           this.address = address;
           return this;
        }
  
        public Builder gender(Gender gender)
        {
           this.gender = gender;
           return this;
        }
  
        //      public Builder name(Name name)
        //      {
        //         this.name = name;
        //         return this;
        //      }
  
        public Builder userImage(byte[] userImage)
        {
           this.userImage = userImage;
           return this;
        }
  
        public Builder isVerified(boolean isVerified)
        {
           this.isVerified = isVerified;
           return this;
        }
  
        public UserImpl build()
        {
           return new UserImpl(address, gender, userImage, isVerified);
        }
     }
  
     @JsonCreator
     public UserImpl(@JsonProperty("address") Address address, @JsonProperty("gender") Gender gender, @JsonProperty("userImage") byte[] userImage,
           @JsonProperty("verified") boolean isVerified)
     {
        super();
        this.address = address;
        this.gender = gender;
        this.userImage = userImage;
        this.isVerified = isVerified;
     }
  
     public Address getAddress()
     {
        return address;
     }
  
     public Gender getGender()
     {
        return gender;
         }
  
     public byte[] getUserImage()
     {
        return userImage;
     }
  
     public boolean isVerified()
     {
        return isVerified;
     }
  
     @Override
     public String toString()
     {
        StringBuilder builder2 = new StringBuilder();
        builder2.append("UserImpl [address=");
        builder2.append(address);
        builder2.append(", gender=");
        builder2.append(gender);
        builder2.append(", isVerified=");
        builder2.append(isVerified);
        builder2.append(", name=");
        builder2.append(", userImage=");
        builder2.append(Arrays.toString(userImage));
        builder2.append("]");
        return builder2.toString();
     }
  
  }
  
  package com.art.starter.jackson_starter;
  
  import org.codehaus.jackson.annotate.JsonCreator;
  import org.codehaus.jackson.annotate.JsonProperty;
  
  public final class AddressImpl implements Address
  {
     private final String city;
     private final String country;
     private final String street;
     private final String state;
     private final int zip;
  
     public static class AddressBuilder
     {
        private String city;
        private String country;
        private String street;
        private String state;
        private int zip;
  
        public AddressBuilder setCity(String city)
        {
           this.city = city;
           return this;
        }
  
        public AddressBuilder setCountry(String country)
        {
           this.country = country;
           return this;
        }
  
        public AddressBuilder setStreet(String street)
        {
           this.street = street;
           return this;
        }
  
        public AddressBuilder setState(String state)
        {
           this.state = state;
           return this;
        }
  
        public AddressBuilder setZip(int zip)
        {
           this.zip = zip;
           return this;
        }
  
        public AddressImpl build()
        {
           return new AddressImpl(city, country, street, state, zip);
        }
  
     }
  
     @JsonCreator
     public AddressImpl(@JsonProperty("city") String city, @JsonProperty("country") String country, @JsonProperty("street") String street,
           @JsonProperty("state") String state, @JsonProperty("zip") int zip)
     {
        this.city = city;
        this.country = country;
        this.street = street;
        this.state = state;
        this.zip = zip;
     }
  
     public String getCity()
     {
        return city;
     }
  
     public String getCountry()
     {
        return country;
     }
  
     public String getStreet()
     {
        return street;
     }
  
     public String getState()
     {
        return state;
     }
  
     public int getZip()
     {
        return zip;
     }
  
     @Override
     public String toString()
     {
        StringBuilder builder = new StringBuilder();
        builder.append("AddressImpl [city=");
        builder.append(city);
        builder.append(", country=");
        builder.append(country);
        builder.append(", state=");
        builder.append(state);
        builder.append(", street=");
        builder.append(street);
        builder.append(", zip=");
        builder.append(zip);
        builder.append("]");
        return builder.toString();
     }
  
  }
  </code></pre>
  
  <p>The issue appears to be with Address. I get this exception:</p>
  
  <pre><code>Exception in thread "main" org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.art.starter.jackson_starter.Address, problem: abstract types can only be instantiated with additional type information
   at [Source: java.io.StringReader@785f8172; line: 1, column: 2]
      at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
      at org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:212)
      at org.codehaus.jackson.map.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:97)
      at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:230)
      at org.codehaus.jackson.map.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:595)
      at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:472)
      at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
      at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2391)
      at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1614)
      at com.art.starter.jackson_starter.App.main(App.java:56)
  </code></pre>
  
  <p>I am sure this is because there is no way for Jackson to resolve Address which is an interface to AddressImpl which is a concrete implementation. I have been poking through the docs and have looked at a few articles regarding the @JsonDeserialize(as=AddressImpl.class),but it didn't work. So I am stumped. Has anyone ever gotten this to work, is it even supported?</p>
  
  <p>It works like a champ if I replace <code>Address</code> with <code>AddressImpl</code> in the <code>UserImpl</code> class.</p>