Search code examples
javajsonjacksonrobospicegoogle-http-client

Parse anonymous array from JSON result with Google HTTP Client Library


My REST service respons with the following data:

[
    {
        "name": "Bart",
        "age": 10
    },
    {
        "name": "Homer",
        "age": 42
    },
    {
        "name": "Marjorie",
        "age": 34
    }
]

The result set is an array of objects which I want to automatically parse with Google's HTTP Client library. Therefore I created a SimpsonResult and Simpson class:

SimpsonResult.java

public class SimpsonResult {

  private List<Simpson> simpsons;

  public SimpsonResult() {
  }

  public List<Simpson> getSimpsons() {
    return simpsons;
  }

  public void setSimpsons(List<Simpson> simpsons) {
    this.simpsons = simpsons;
  }

}

Simpson.java

public class Simpson {

  @Key
  private String name;

  @Key
  private int age;

  public Simpson() {
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

}

Now I want to query my backend and automatically map the response into a SimpsonResult. Therefore I wrote the following code:

@Override
public SimpsonResult loadDataFromNetwork() throws IOException {
  HttpRequestFactory requestFactory = getHttpRequestFactory();
  GenericUrl url = new GenericUrl(baseUrl);
  HttpRequest request = requestFactory.buildGetRequest(url);
  request.setParser(new JacksonFactory().createJsonObjectParser());
  return request.execute().parseAs(SimpsonResult.class);
}

But when I execute the code, then I get a parser exception from com.google.api.client.json.JsonParser.

When I map it into a string (request.execute().parseAsString()), then it works.

So I think that my mapping declaration is wrong?


Solution

  • You can use Type for parsing parameterized classes as below

    Type type = new TypeToken<ArrayList<SimpsonResult>>() {}.getType();
    request.execute().parseAs(type);
    

    Creating an extra class, extending parameterized classes like ArrayList, just for parsing is a not recommended. Hence your function can be written as

    @Override
    public ArrayList<SimpsonResult> loadDataFromNetwork() throws IOException {
      HttpRequestFactory requestFactory = getHttpRequestFactory();
      GenericUrl url = new GenericUrl(baseUrl);
      HttpRequest request = requestFactory.buildGetRequest(url);
    
      Type type = new TypeToken<ArrayList<SimpsonResult>>() {}.getType();
      return request.execute().parseAs(type);
    }