Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically handle json response array/object using Gson

Tags:

java

android

gson

I am facing a problem , sometimes Json response returns an array of objects , sometimes object itself , how we can handle dynamically in the response class. In the current eg :results sometimes gets an array of objects

 "\"results\": " +
            "[{" +

and sometimes object itself

 "\"results\": " +
            "{" +

Eg:

How we can handle this ?

Gson gson = new Gson();
    SearchResponse response=new SearchResponse();
    response= gson.fromJson("{" +
            "\"completed_in\": 0.047," +
            "\"max_id\": 291771567376039936," +
            "\"max_id_str\": \"291771567376039936\"," +
            "\"next_page\": \"?page=2&max_id=291771567376039936&q=javacodegeeks\"," +
            "\"page\": 1," +
            "\"query\": \"javacodegeeks\"," +
            "\"refresh_url\": \"?since_id=291771567376039936&q=javacodegeeks\"," +
            "\"results\": " +
            "{" +
            "\"created_at\": \"Thu, 17 Jan 2013 04:58:57 +0000\"," +
            "\"from_user\": \"hkokko\"," +
            "\"from_user_id\": 24726686," +
            "\"from_user_id_str\": \"24726686\"," +
            " \"from_user_name\": \"Hannu Kokko\"," +
            " \"geo\": null," +
            "\"id\": 291771567376039936," +
            "\"id_str\": \"291771567376039936\"," +
            "\"iso_language_code\": \"en\"," +
            " \"metadata\": {" +
            "\"result_type\": \"recent\"}," +
            "\"profile_image_url\": \"hjh\"," +
            "\"profile_image_url_https\": \"kkj\"," +
            "\"source\": \"<a href="hj;\"," +
            "\"text\": \"Continuous Deployment: Are You Afraid It Might Work? jh\"," +
            "\"to_user\": null," +
            "\"to_user_id\": 0," +
            "\"to_user_id_str\": \"0\"," +
            "\"to_user_name\": null" +
            " }," +
            "\"results_per_page\": 15," +
            "\"since_id\": 0," +
            "\"since_id_str\": \"0\"" +
            "}", SearchResponse.class);
    System.out.println(response.toString());

Kindly assist...

Can anyone give any suggestions by using different jars to achieve this?

like image 435
Rockin Avatar asked Jan 17 '13 06:01

Rockin


2 Answers

i found a solution for this ,i felt to share this..The code will automatically convert ..if excepted response is arraylist in response class....then if object is coming in response then add to arraylist else if arraylist it will take the same list. we need hook change the response bfore it calls fromJson.

public class ArrayAdapter<T> extends TypeAdapter<List<T>> {
    private Class<T> adapterclass;

    public ArrayAdapter(Class<T> adapterclass) {

        this.adapterclass = adapterclass;
    }

    public List<T> read(JsonReader reader) throws IOException {


        List<T> list = new ArrayList<T>();

        Gson gson = new Gson();

        if (reader.peek() == JsonToken.BEGIN_OBJECT) {

            T inning = (T) gson.fromJson(reader, adapterclass);
            list.add(inning);

        } else if (reader.peek() == JsonToken.BEGIN_ARRAY) {

            reader.beginArray();
            while (reader.hasNext()) {
                T inning = (T) gson.fromJson(reader, adapterclass);
                list.add(inning);
            }
            reader.endArray();

        } else {
            reader.skipValue();
        }

        return list;
    }

    public void write(JsonWriter writer, List<T> value) throws IOException {

    }

}

public class ArrayAdapterFactory implements TypeAdapterFactory {

  @SuppressWarnings({ "unchecked" })
  @Override
  public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {

      ArrayAdapter typeAdapter = null;
      try {
          if (type.getRawType() == List.class)
          {

              typeAdapter = new ArrayAdapter(
                      (Class) ((ParameterizedType) type.getType())
                              .getActualTypeArguments()[0]);
          }
      } catch (Exception e) {
          e.printStackTrace();
      }

      return typeAdapter;
}

then just call

 Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ArrayAdapterFactory()).create();
 SearchResponse response;
 esponse= gson.fromJson("your json string", SearchResponse.class)
like image 103
Rockin Avatar answered Oct 25 '22 22:10

Rockin


You would need to write a custom deserializer that checks the type of results in the JSON then acts accordingly.

Your POJO will contain an array for results and if your incoming JSON only has a single object you'll need to fix that. One way is to modify the JSON then deserialize it:

class SearchResponseDeserializer implements JsonDeserializer<SearchResponse> {
  public SearchResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {

    if (json.getAsJsonObject().get("results").isJsonObject()) {
      //modify JSON: change results to be an array
      // ...
    }

    return new Gson().fromJson(json, SearchResults.class);

  }
}

Or, fix the server, of course. It should always be returning an array to avoid this issue.

like image 20
Brian Roach Avatar answered Oct 25 '22 22:10

Brian Roach