Retrofit gson with dynamic keys
I've managed to get it to work without a dynamic key. By following this tutorial with this json:
Currently, I'm using Retrofit and trying to get a response with dynamic keys. However, the response body is always null:

This is the response format:
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
In APIUtils.java
public static CityService getCitiesService()
return RetrofitClient.getClient(BASE_URL).create(CityService.class);
In CityService.java
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities();
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities(@Query("tagged") String tags);
In CityResponse.java:
public class CityResponse
/*@SerializedName("results")
@Expose*/ // is this the correct way?
private Map<String, CityDetails> city = new HashMap<>();
public Map<String, CityDetails> getCity()
return city;
public void setCity(Map<String, CityDetails> elemDetails)
this.city = elemDetails;
In CityDetails.java
public class CityDetails
@SerializedName("cityID")
@Expose
private String cityID;
@SerializedName("priceRange")
@Expose
private Integer priceRange;
public String getCityID()
return cityID;
public void setCityID(String cityID)
this.cityID = cityID;
public Integer getPriceRange()
return priceRange;
public void setPriceRange(Integer priceRange)
this.priceRange = priceRange;
In HomeFragment.java
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_home, null);
// 2nd api call
mServiceCity = ApiUtils.getCitiesService();
loadCities();
return rootView;
public void loadCities()
mServiceCity.getCities().enqueue(new Callback<CityResponse>()
@Override
public void onResponse(Call<CityResponse> call, Response<CityResponse> response)
// !!! WHY IS THE RESPONSE BODY EMPTY???
if(response.isSuccessful())
// adapter.updateCities(response.body().getCity());
Log.d("MainActivity", "posts loaded from API"+ response.body().getCity());
else
int statusCode = response.code();
// handle request errors depending on status code
@Override
public void onFailure(Call<CityResponse> call, Throwable t)
//showErrorMessage();
Log.d("MainActivity", "error loading from API");
);
|
show 12 more comments
I've managed to get it to work without a dynamic key. By following this tutorial with this json:
Currently, I'm using Retrofit and trying to get a response with dynamic keys. However, the response body is always null:

This is the response format:
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
In APIUtils.java
public static CityService getCitiesService()
return RetrofitClient.getClient(BASE_URL).create(CityService.class);
In CityService.java
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities();
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities(@Query("tagged") String tags);
In CityResponse.java:
public class CityResponse
/*@SerializedName("results")
@Expose*/ // is this the correct way?
private Map<String, CityDetails> city = new HashMap<>();
public Map<String, CityDetails> getCity()
return city;
public void setCity(Map<String, CityDetails> elemDetails)
this.city = elemDetails;
In CityDetails.java
public class CityDetails
@SerializedName("cityID")
@Expose
private String cityID;
@SerializedName("priceRange")
@Expose
private Integer priceRange;
public String getCityID()
return cityID;
public void setCityID(String cityID)
this.cityID = cityID;
public Integer getPriceRange()
return priceRange;
public void setPriceRange(Integer priceRange)
this.priceRange = priceRange;
In HomeFragment.java
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_home, null);
// 2nd api call
mServiceCity = ApiUtils.getCitiesService();
loadCities();
return rootView;
public void loadCities()
mServiceCity.getCities().enqueue(new Callback<CityResponse>()
@Override
public void onResponse(Call<CityResponse> call, Response<CityResponse> response)
// !!! WHY IS THE RESPONSE BODY EMPTY???
if(response.isSuccessful())
// adapter.updateCities(response.body().getCity());
Log.d("MainActivity", "posts loaded from API"+ response.body().getCity());
else
int statusCode = response.code();
// handle request errors depending on status code
@Override
public void onFailure(Call<CityResponse> call, Throwable t)
//showErrorMessage();
Log.d("MainActivity", "error loading from API");
);
What is the response you are expecting?
– Ümañg ßürmån
Nov 14 '18 at 9:02
Hi this is the response: "dynamic1": "cityID": "id1", "priceRange": 15 , "dynamic2": "cityID": "id2", "priceRange": 15
– user1872384
Nov 14 '18 at 9:03
Okay, you mean to say this is not coming, it's always coming empty right?
– Ümañg ßürmån
Nov 14 '18 at 9:03
Your CityResponse model is wrong as there is no @SerializedName(), how will it know from which key it needs to parse..!!
– Prashanth Verma
Nov 14 '18 at 9:06
@Ümañgßürmån updated the questions with breakpoint at the response
– user1872384
Nov 14 '18 at 9:09
|
show 12 more comments
I've managed to get it to work without a dynamic key. By following this tutorial with this json:
Currently, I'm using Retrofit and trying to get a response with dynamic keys. However, the response body is always null:

This is the response format:
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
In APIUtils.java
public static CityService getCitiesService()
return RetrofitClient.getClient(BASE_URL).create(CityService.class);
In CityService.java
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities();
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities(@Query("tagged") String tags);
In CityResponse.java:
public class CityResponse
/*@SerializedName("results")
@Expose*/ // is this the correct way?
private Map<String, CityDetails> city = new HashMap<>();
public Map<String, CityDetails> getCity()
return city;
public void setCity(Map<String, CityDetails> elemDetails)
this.city = elemDetails;
In CityDetails.java
public class CityDetails
@SerializedName("cityID")
@Expose
private String cityID;
@SerializedName("priceRange")
@Expose
private Integer priceRange;
public String getCityID()
return cityID;
public void setCityID(String cityID)
this.cityID = cityID;
public Integer getPriceRange()
return priceRange;
public void setPriceRange(Integer priceRange)
this.priceRange = priceRange;
In HomeFragment.java
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_home, null);
// 2nd api call
mServiceCity = ApiUtils.getCitiesService();
loadCities();
return rootView;
public void loadCities()
mServiceCity.getCities().enqueue(new Callback<CityResponse>()
@Override
public void onResponse(Call<CityResponse> call, Response<CityResponse> response)
// !!! WHY IS THE RESPONSE BODY EMPTY???
if(response.isSuccessful())
// adapter.updateCities(response.body().getCity());
Log.d("MainActivity", "posts loaded from API"+ response.body().getCity());
else
int statusCode = response.code();
// handle request errors depending on status code
@Override
public void onFailure(Call<CityResponse> call, Throwable t)
//showErrorMessage();
Log.d("MainActivity", "error loading from API");
);
I've managed to get it to work without a dynamic key. By following this tutorial with this json:
Currently, I'm using Retrofit and trying to get a response with dynamic keys. However, the response body is always null:

This is the response format:
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
In APIUtils.java
public static CityService getCitiesService()
return RetrofitClient.getClient(BASE_URL).create(CityService.class);
In CityService.java
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities();
@GET("/SAGetStrollAwayCity")
Call<CityResponse> getCities(@Query("tagged") String tags);
In CityResponse.java:
public class CityResponse
/*@SerializedName("results")
@Expose*/ // is this the correct way?
private Map<String, CityDetails> city = new HashMap<>();
public Map<String, CityDetails> getCity()
return city;
public void setCity(Map<String, CityDetails> elemDetails)
this.city = elemDetails;
In CityDetails.java
public class CityDetails
@SerializedName("cityID")
@Expose
private String cityID;
@SerializedName("priceRange")
@Expose
private Integer priceRange;
public String getCityID()
return cityID;
public void setCityID(String cityID)
this.cityID = cityID;
public Integer getPriceRange()
return priceRange;
public void setPriceRange(Integer priceRange)
this.priceRange = priceRange;
In HomeFragment.java
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_home, null);
// 2nd api call
mServiceCity = ApiUtils.getCitiesService();
loadCities();
return rootView;
public void loadCities()
mServiceCity.getCities().enqueue(new Callback<CityResponse>()
@Override
public void onResponse(Call<CityResponse> call, Response<CityResponse> response)
// !!! WHY IS THE RESPONSE BODY EMPTY???
if(response.isSuccessful())
// adapter.updateCities(response.body().getCity());
Log.d("MainActivity", "posts loaded from API"+ response.body().getCity());
else
int statusCode = response.code();
// handle request errors depending on status code
@Override
public void onFailure(Call<CityResponse> call, Throwable t)
//showErrorMessage();
Log.d("MainActivity", "error loading from API");
);
edited Nov 14 '18 at 9:11
user1872384
asked Nov 14 '18 at 8:59
user1872384user1872384
4,18553262
4,18553262
What is the response you are expecting?
– Ümañg ßürmån
Nov 14 '18 at 9:02
Hi this is the response: "dynamic1": "cityID": "id1", "priceRange": 15 , "dynamic2": "cityID": "id2", "priceRange": 15
– user1872384
Nov 14 '18 at 9:03
Okay, you mean to say this is not coming, it's always coming empty right?
– Ümañg ßürmån
Nov 14 '18 at 9:03
Your CityResponse model is wrong as there is no @SerializedName(), how will it know from which key it needs to parse..!!
– Prashanth Verma
Nov 14 '18 at 9:06
@Ümañgßürmån updated the questions with breakpoint at the response
– user1872384
Nov 14 '18 at 9:09
|
show 12 more comments
What is the response you are expecting?
– Ümañg ßürmån
Nov 14 '18 at 9:02
Hi this is the response: "dynamic1": "cityID": "id1", "priceRange": 15 , "dynamic2": "cityID": "id2", "priceRange": 15
– user1872384
Nov 14 '18 at 9:03
Okay, you mean to say this is not coming, it's always coming empty right?
– Ümañg ßürmån
Nov 14 '18 at 9:03
Your CityResponse model is wrong as there is no @SerializedName(), how will it know from which key it needs to parse..!!
– Prashanth Verma
Nov 14 '18 at 9:06
@Ümañgßürmån updated the questions with breakpoint at the response
– user1872384
Nov 14 '18 at 9:09
What is the response you are expecting?
– Ümañg ßürmån
Nov 14 '18 at 9:02
What is the response you are expecting?
– Ümañg ßürmån
Nov 14 '18 at 9:02
Hi this is the response: "dynamic1": "cityID": "id1", "priceRange": 15 , "dynamic2": "cityID": "id2", "priceRange": 15
– user1872384
Nov 14 '18 at 9:03
Hi this is the response: "dynamic1": "cityID": "id1", "priceRange": 15 , "dynamic2": "cityID": "id2", "priceRange": 15
– user1872384
Nov 14 '18 at 9:03
Okay, you mean to say this is not coming, it's always coming empty right?
– Ümañg ßürmån
Nov 14 '18 at 9:03
Okay, you mean to say this is not coming, it's always coming empty right?
– Ümañg ßürmån
Nov 14 '18 at 9:03
Your CityResponse model is wrong as there is no @SerializedName(), how will it know from which key it needs to parse..!!
– Prashanth Verma
Nov 14 '18 at 9:06
Your CityResponse model is wrong as there is no @SerializedName(), how will it know from which key it needs to parse..!!
– Prashanth Verma
Nov 14 '18 at 9:06
@Ümañgßürmån updated the questions with breakpoint at the response
– user1872384
Nov 14 '18 at 9:09
@Ümañgßürmån updated the questions with breakpoint at the response
– user1872384
Nov 14 '18 at 9:09
|
show 12 more comments
1 Answer
1
active
oldest
votes
Personally I'd drop the CityResponse model and just work with Map<String, CityDetails>.
The retrofit interface can then be:
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities();
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities(@Query("tagged") String tags);
In your scenario, the response body is empty because CityResponse would map to a json like:
"city":
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
However, you don't have a root element called city. The json itself can already be mapped to a java Map.
Hope this helps.
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
1
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53296312%2fretrofit-gson-with-dynamic-keys%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Personally I'd drop the CityResponse model and just work with Map<String, CityDetails>.
The retrofit interface can then be:
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities();
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities(@Query("tagged") String tags);
In your scenario, the response body is empty because CityResponse would map to a json like:
"city":
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
However, you don't have a root element called city. The json itself can already be mapped to a java Map.
Hope this helps.
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
1
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
add a comment |
Personally I'd drop the CityResponse model and just work with Map<String, CityDetails>.
The retrofit interface can then be:
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities();
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities(@Query("tagged") String tags);
In your scenario, the response body is empty because CityResponse would map to a json like:
"city":
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
However, you don't have a root element called city. The json itself can already be mapped to a java Map.
Hope this helps.
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
1
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
add a comment |
Personally I'd drop the CityResponse model and just work with Map<String, CityDetails>.
The retrofit interface can then be:
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities();
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities(@Query("tagged") String tags);
In your scenario, the response body is empty because CityResponse would map to a json like:
"city":
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
However, you don't have a root element called city. The json itself can already be mapped to a java Map.
Hope this helps.
Personally I'd drop the CityResponse model and just work with Map<String, CityDetails>.
The retrofit interface can then be:
public interface CityService
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities();
@GET("/SAGetStrollAwayCity")
Call<Map<String, CityDetails>> getCities(@Query("tagged") String tags);
In your scenario, the response body is empty because CityResponse would map to a json like:
"city":
"dynamic1":
"cityID": "id1",
"priceRange": 15
,
"dynamic2":
"cityID": "id2",
"priceRange": 15
However, you don't have a root element called city. The json itself can already be mapped to a java Map.
Hope this helps.
answered Nov 14 '18 at 10:46
FredFred
8,34512644
8,34512644
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
1
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
add a comment |
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
1
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
you are a genius!!! What's your payapl account? I'll buy you beer :D
– user1872384
Nov 14 '18 at 11:00
1
1
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
:D That's fine, no worries! Glad it helped! Buy the beer to someone else in more need than me :D
– Fred
Nov 14 '18 at 11:03
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53296312%2fretrofit-gson-with-dynamic-keys%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What is the response you are expecting?
– Ümañg ßürmån
Nov 14 '18 at 9:02
Hi this is the response: "dynamic1": "cityID": "id1", "priceRange": 15 , "dynamic2": "cityID": "id2", "priceRange": 15
– user1872384
Nov 14 '18 at 9:03
Okay, you mean to say this is not coming, it's always coming empty right?
– Ümañg ßürmån
Nov 14 '18 at 9:03
Your CityResponse model is wrong as there is no @SerializedName(), how will it know from which key it needs to parse..!!
– Prashanth Verma
Nov 14 '18 at 9:06
@Ümañgßürmån updated the questions with breakpoint at the response
– user1872384
Nov 14 '18 at 9:09