deserialize list typed with interface

884 views
Skip to first unread message

Mike S

unread,
Jan 3, 2012, 5:49:12 PM1/3/12
to google-gson
Hi

Is it possible to deserialize json into a list typed with an
interface?

Say I have an interface Dog

public interface Dog {
String sayBark();
}

and a class Animal

public class Animal {
List<Dog> getDogs();
}

Is there a way to tell Gson what implementation of Dog to use in the
deserialization?

Deserialization works fine with say

List<DogImpl> getDogs();

but I'd rather return the list typed with an interface rather than the
implementation.

Thanks in advance

Jesse Wilson

unread,
Jan 3, 2012, 8:23:01 PM1/3/12
to googl...@googlegroups.com
You'll need to register a type adapter for Dog. Here's a full example that'll work with Gson 2.1:

  public static void main(String[] args) {
    TypeAdapter<Dog> dogTypeAdapter = new DogTypeAdapter().nullSafe();
    Gson gson = new GsonBuilder()
        .registerTypeAdapter(Dog.class, dogTypeAdapter)
        .create();

    Type listOfDogsType = new TypeToken<List<Dog>>() {}.getType();

    List<Dog> dogs = Arrays.<Dog>asList(
        new DefaultDog("Butters", "Irish Terrier"),
        new DefaultDog("McFly", "Airedale Terrier"));
    System.out.println(gson.toJson(dogs, listOfDogsType));

    String json = "["
        + "{\"name\":\"Butters\",\"breed\":\"Irish Terrier\"},"
        + "{\"name\":\"McFly\",\"breed\":\"Airedale Terrier\"}"
        + "]";
    System.out.println(gson.fromJson(json, listOfDogsType));
  }

  interface Dog {
    String getName();
    String getBreed();
  }

  static class DefaultDog implements Dog {
    private final String name;
    private final String breed;

    DefaultDog(String name, String breed) {
      this.name = name;
      this.breed = breed;
    }

    public String getName() {
      return name;
    }

    public String getBreed() {
      return breed;
    }

    @Override public String toString() {
      return name + " (" + breed + ")";
    }
  }

  private static class DogTypeAdapter extends TypeAdapter<Dog> {
    @Override public void write(JsonWriter out, Dog dog) throws IOException {
      out.beginObject();
      out.name("name");
      out.value(dog.getName());
      out.name("breed");
      out.value(dog.getBreed());
      out.endObject();
    }

    @Override public Dog read(JsonReader in) throws IOException {
      String name = null;
      String breed = null;
      in.beginObject();
      while (in.hasNext()) {
        String key = in.nextName();
        if (key.equals("name")) {
          name = in.nextString();
        } else if (key.equals("breed")) {
          breed = in.nextString();
        } else {
          in.skipValue();
        }
      }
      in.endObject();
      return new DefaultDog(name, breed);
    }
  }

Mike S

unread,
Jan 4, 2012, 12:22:20 PM1/4/12
to google-gson
Thanks this is helpful I'm getting further and have it working for the
String fields in my class.
But what if the interface dog not have simple String attributes
Say it is something like this
 interface Dog {     List<IBreed> getBreeds();    Map<String, String>
getAttributes();   }
Thanks

Mike S

unread,
Jan 12, 2012, 11:27:43 AM1/12/12
to google-gson
Any ideas here?

In the example provided, the JsonReader class only has methods to get
simple types
String, Int, Double, Boolean, Long

Is it even possible to deserialize something more complex in this case
like a Map?

Thanks

Jesse Wilson

unread,
Jan 13, 2012, 5:43:37 PM1/13/12
to googl...@googlegroups.com
Mike,

You'll want to write a custom type adapter. The Gson user guide covers doing that in depth. Your easiest strategy will be to use JsonSerializer and JsonDeserializer. 

Cheers,
Jesse

Mike S

unread,
Feb 6, 2012, 2:34:25 PM2/6/12
to google-gson
I ended up doing something a little different. Seems simpler to me as
well and fit my need.

In the implementation class I declare the object at the top

List<DogImpl> dogs;

but I change it back to return the interface in the get method

public List <Dog> getDogs() {
return Collections.<Dog>unmodifiableList(dogs);
}

Thanks
Mike
Reply all
Reply to author
Forward
0 new messages