Skip to content

Instantly share code, notes, and snippets.

@peerapongsam
Last active August 1, 2020 13:01
Show Gist options
  • Save peerapongsam/a7771e49562d74843c64f9cf53adbe52 to your computer and use it in GitHub Desktop.
Save peerapongsam/a7771e49562d74843c64f9cf53adbe52 to your computer and use it in GitHub Desktop.
Gson Dynamic Key Deserializer
package me.peerapong.android_dynamicjsonkey;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<NumberResponse>() {
}.getType(), new NumberResponse.NumberResponseDeserializer())
.create();
API api = new Retrofit.Builder()
.baseUrl("http://172.20.10.2:8087/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(API.class);
api.getNumber().enqueue(new Callback<NumberResponse>() {
@Override
public void onResponse(Call<NumberResponse> call, Response<NumberResponse> response) {
NumberResponse numberResponse = response.body();
Log.d(TAG, "onResponse: " + numberResponse.getStringNumberMap().toString());
/*
OUTPUT: D/MainActivity: onResponse: {1={id=1.0, name=ONE}, 2={id=2.0, name=TWO}, 3={id=3.0, name=THREE}}
*/
}
@Override
public void onFailure(Call<NumberResponse> call, Throwable t) {
t.printStackTrace();
}
});
}
public interface API {
/*
{
"1": {"id": 1, "name": "ONE"},
"2": {"id": 2, "name": "TWO"},
"3": {"id": 3, "name": "THREE"}
}
*/
@GET("/dynamic.json")
Call<NumberResponse> getNumber();
}
static class NumberResponse {
public Map<String, Number> mStringNumberMap;
public Map<String, Number> getStringNumberMap() {
return mStringNumberMap;
}
public void setStringNumberMap(Map<String, Number> stringNumberMap) {
mStringNumberMap = stringNumberMap;
}
public static class Number {
public int id;
public String name;
@Override
public String toString() {
return "Number{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public static class NumberResponseDeserializer implements JsonDeserializer<NumberResponse> {
@Override
public NumberResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
NumberResponse response = new Gson().fromJson(json, NumberResponse.class);
Map<String, Number> map = new HashMap<>();
map = (Map<String, Number>) new Gson().fromJson(json, map.getClass());
response.setStringNumberMap(map);
return response;
}
}
}
}
@mochadwi
Copy link

mochadwi commented Mar 23, 2020

or if you (future reader) don't mind adding a little (or a lot) performance cost (due to reflections in runtime), use TypeToken for GSON, see the article here: http://findnerd.com/list/view/Parse-Json-Object-with-dynamic-keys-using-Gson-/24094/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment