Parsing JSON response using GSON with dynamic Key - android

This is how my JSON looks like and I have to parse the JSON, how can this be done using GSON
{
"data": {
"a": {
"abc": {
"c": "d"
}
}
}
}
In which "a" is dynamic key which may vary from time to time. I am unable to find a solution right now

Model
public class Model {
private HashMap<String, String> data;
public Model() {
}
}
Convert json string to Hashmap using Gson & prepare data from hashmap
Gson gson = new Gson();
Type typeHashMap = new TypeToken<Map<String, String>>(){}.getType();
Map<String,String> map = gson.fromJson(YOUR_JSON, typeHashMap);
Set<Map.Entry<String, String>> entrySet = data.entrySet();
Iterator iterator = entrySet.iterator ();
for(int j = 0; j < entrySet.size(); j++) {
try {
Map.Entry entry = (Map.Entry) iterator.next();
String key = entry.getKey().toString();
String value = entry.getValue().toString();
//Add it to your list
}
catch(NoSuchElementException e) {
e.printStackTrace();
}
break;
}

I am not sure if internal part abc is known to you or not. If it is known to you then you can surely do it with GSON. You have to create the class for the inner known object as below:
public class ABC {
public C abc;}
Then create the Class for C:
public class C {
public String c;}
Then just pass the ABC class as the hashmap value as below:
public HashMap<String, ABC> a;

Related

How to get data from nested JSON objects using Gson

I would like get countynames from the API and it returns nested objects;
"countries": {
"1": {
"name": "Cyprus",
"nameTurkish": "KKTC",
"nameNative": "Kıbrıs"
},
"2": {
"name": "Turkey",
"nameTurkish": "Türkiye",
"nameNative": "Türkiye"
},
"3": {
"name": "Monaco",
"nameTurkish": "Monako",
"nameNative": "Monaco"
},
and so on there are more than 200 countries and every county has its own "NUMBER_ID". In the end I want to list all "name" information. I think I should use JsonDeserializer but unfortunately I couldn't.
The entire JSON response can be read as a JSONObject that has multiple elements in it that you can iterate through and get different data.
String jsonResponse = ""; // Put the entire JSON response as a String
JSONObject root = new JSONObject(jsonResponse);
JSONArray rootArray = root.getJSONArray("countries"); // root element of the json respons
for (int i = 0; i < rootArray.length(); i++) {
JSONObject number = rootArray.getJSONObject(i);
String country = number.getString("name"); // Get country name
// Here you can add `country` into a List
}
UPDATE:
but there is no array in my JSON file, all of them are objects, every
country is in an object and every object has its own SerializedName
You can read it into JSONOjbect, and instead of using a JSONArray, you can iterate over the length of the JSONObject as below.
try {
JSONObject root = new JSONObject(jsonResponse);
JSONObject countries = root.getJSONObject("countries");
for (int i = 1; i <= countries.length(); i++) {
JSONObject number = countries.getJSONObject(String.valueOf(i));
String country = number.getString("name"); // Get country name
// Here you can add the `country` into a List
}
} catch (JSONException e) {
e.printStackTrace();
}
try using TypeToken.
Gson gson = new Gson();
List<Country> list = gson.fromJson(gson.toJson(what_you_get_data), new TypeToken<ArrayList<Country>>(){}.getType()); //Country is VO class what you make.
Here, you can see that your data looks like HashMap, so I just tried in that way and your data parsed successfully without a glitch:
Create Pojo's:
public class Countries {
private HashMap<String, Country> countries;
public HashMap<String, Country> getCountries() { return countries; }
public void setCountries(HashMap<String, Country> countries) { this.countries = countries; }
}
public class Country {
private String name;
private String nameTurkish;
private String nameNative;
public String getName() { return name; }
public void setName(String name) { this.name = name;}
public String getNameTurkish() { return nameTurkish; }
public void setNameTurkish(String nameTurkish) { this.nameTurkish = nameTurkish; }
public String getNameNative() { return nameNative; }
public void setNameNative(String nameNative) { this.nameNative = nameNative; }
}
Create a Gson Object and parse it:
Gson gson = new Gson();
// Countries Object
Type testC = new TypeToken<Countries>(){}.getType();
Countries ob = gson.fromJson(test, testC);
String newData = gson.toJson(ob.getCountries());
System.out.println("New Data: "+newData);
// All country in HashMap
Type country = new TypeToken<HashMap<String, Country>>(){}.getType();
HashMap<String, Country> countryHashMap = gson.fromJson(newData, country);
// Print All HashMap Country
for (Map.Entry<String, Country> set : countryHashMap.entrySet()) {
System.out.println("==> "+set.getKey() + " = " + set.getValue());
}
Output:
I/System.out: ==> 1 = Country{name='Cyprus', nameTurkish='KKTC', nameNative='Kıbrıs'}
I/System.out: ==> 2 = Country{name='Turkey', nameTurkish='Türkiye', nameNative='Türkiye'}
I/System.out: ==> 3 = Country{name='Monaco', nameTurkish='Monako', nameNative='Monaco'}

How to search a key in JSON Object if format is not constant?

In my android application, I have saved my form's data in a json, the parent of this json is a json object that may contains simple key value pairs, or a JSON Array, or sub json object.
The structure of Parent JSON Object is basically changing on run time and i have to add a function that can find value saved against any key.
For example, if I have the following JSON and I want to get value of key5. Is there any way to get the value?
A solution that i want to try is loop through the json but i am unable to check what is stored on index of json object mean is it a simple string, a json array or a sub json object.
{
"key1": "value of key 1",
"key2": "value of key 2",
"key3": "value of key 3",
"subjson": {
"key4": "value of key 4",
"key5": "value of key 5",
"key6": "value of key 6"
},
"subjsonArray": [
{
"key7": "value of key 7",
"key8": "value of key 8"
},
{
"key9": "value of key 9",
"key10": "value of key 10"
}
]
}
Can someone please help me out with this. Any help will be appreciated.
Here is an example to handle json
JsonElement jsonElement = new Gson().fromJson("YOUR JSON", JsonElement.class);
if(jsonElement.isJsonObject()){
jsonElement.getAsJsonObject("key5");
}else if(jsonElement.isJsonArray()){
jsonElement.getAsJsonArray("key5");
}
If you need to iterate over json you can use
Set<Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
String key = entry.getKey();
JsonElement value = jsonObject.get(entry.getKey()));
}
You need to import Gson to your project
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}
More information how to use Gson:
https://github.com/google/gson
Let me start by saying this - you should try to fix the non-constant Json issue before finding a solution for this.
But if it's out of your control, here's what might work.
This handles nested JsonObject and/or JsonArray.
You can just copy/paste those functions.
All you have to do is call this function - getValueFromNonConstantJson(...)
private void getValueFromNonConstantJson(String fullJson, String key) {
Gson gson = new Gson();
final Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> objectMap = gson.fromJson(fullJson, mapType);
String value = "";
value = getValueFromMap(objectMap, key);
}
private String getValueFromMap(Map<String, Object> objectMap, String key) {
String result = "";
// let's quickly check is the root object contains the key you want
// if it does, you don't have to start the for loop at all
if(objectMap.containsKey("key5")) {
Object key5Value = objectMap.get("key5");
if(key5Value instanceof JsonObject) {
JsonObject jsonObject = (JsonObject) key5Value;
result = getValueFromJsonObject(jsonObject, key);
} else if (key5Value instanceof JsonArray) {
JsonArray jsonArray = (JsonArray) key5Value;
result = getValueFromJsonArray(jsonArray, key);
}
} else {
for(Map.Entry<String, Object> entry : objectMap.entrySet()) {
if(entry.getValue() instanceof JsonObject) {
JsonObject jsonObject = (JsonObject) entry.getValue();
result = getValueFromJsonObject(jsonObject, key);
if(!result.isEmpty()) {
// you found it.
break;
}
} else if (entry.getValue() instanceof JsonArray) {
JsonArray jsonArray = (JsonArray) entry.getValue();
result = getValueFromJsonArray(jsonArray, key);
if(!result.isEmpty()) {
// you found it.
break;
}
}
}
}
return result;
}
private String getValueFromJsonObject(JsonObject subJsonObject, String key) {
String value = "";
Gson gson = new Gson();
final Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> objectMap = gson.fromJson(subJsonObject, mapType);
value = getValueFromMap(objectMap, key);
return value;
}
private String getValueFromJsonArray(JsonArray subJsonArray, String key) {
String value = "";
Gson gson = new Gson();
Object[] objectArr = gson.fromJson(subJsonArray, Object[].class);
for(Object object : objectArr) {
if(object instanceof Map) {
Map<String, Object> objectMap = (Map<String, Object>) object;
value = getValueFromMap(objectMap, key);
if(!value.isEmpty()) {
break;
}
}
}
return value;
}
Using Retrofit, you can achieve it like this :
Below is the Model class which extends JsonElement as the JsonResponse structure is undefined
public class JsonResponse extends JsonElement {
//Key will be of type JsonElement
#SerializedName("key1")
public JsonElement key1;
//Return type is JsonElement since it is decided at Runtime
public JsonElement getKey1() {
if (key1 instanceof JsonArray) {
List<JsonObject> objectList = getArray(key1);
return (JsonElement) objectList; //If key is of type JsonArray then return JsonArray
} else {
return getObject(key1); //If key is of type JsonObject then return JsonObject
}
}
public void setKey1(JsonElement key1) {
this.key1 = key1;
}
private JsonObject getObject(JsonElement data) {
Type type = new TypeToken<JsonObject>() {}.getType();
return new Gson().fromJson(data, type);
}
private List<JsonObject> getArray(JsonElement data) {
Type type = new TypeToken<List<JsonObject>>() {}.getType();
return new Gson().fromJson(((JsonObject) data).get("key1"), type);
}
//Method from super class
#Override
public JsonElement deepCopy() {
return null;
}
}
Same process can be repeated for the keys whose return-type is not defined.
Then in your ClassA you can fetch data by directly accessing key1 element from JsonResponse class.
In your ClassA, check if this element key1 is of type JsonArray or not and fetch data accordingly.
Using JSONObject a possible implementation can be
private Object interateNestedJson(JSONObject jsonObject, String keySearch) {
for (Iterator<String> it = jsonObject.keys(); it.hasNext(); ) {
try {
String jsonKey = it.next();
Object jsonValue = jsonObject.get(jsonKey);
if (jsonValue instanceof JSONArray) {
Object foundInArray = iterateArray((JSONArray) jsonValue, keySearch);
if(foundInArray != null) {
return foundInArray;
}
} else if (jsonValue instanceof JSONObject) {
Object foundInObject = interateNestedJson(jsonObject, keySearch);
if(foundInObject != null) {
return foundInObject;
}
} else {
return jsonValue; // return primitive value
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return null;
}
private Object iterateArray(JSONArray jsonArray, String keySearch) throws JSONException {
for (int i = 0; i < jsonArray.length(); i++) {
Object jsonObject = jsonArray.get(i);
if (jsonObject instanceof JSONObject) {
Object inNested = interateNestedJson((JSONObject) jsonObject, keySearch);
if (inNested != null) {
return inNested;
}
} else if (jsonObject instanceof JSONArray) {
Object inArray = iterateArray((JSONArray) jsonObject, keySearch);
if (inArray != null) {
return inArray;
}
}
}
return null;
}
And you start the search like this
JSONObject json = new JSONObject(jsonString);
Object value = interateNestedJson(jsonObject, "key5");
I have no time to test this now, if it has an error I'll try to fix it later

convert a json object response into array and get both key and value android

I have a json response which is dynamic such that even the key name and index no.can change
{
"Assigned": {
"DC": 7,
"EmpCode": "E0104",
"FS": 8
}
}
I want to convert it into JsonArray and fetch all the key names and values dynamically under the object 'Assigned'.But I am only getting the value name by trying this.
try {
//converting dynamic jsonobject to json array and fetching value as well as key name
JSONObject jsonObject = response.getJSONObject("Assigned");
Iterator x = jsonObject.keys();
JSONArray jsonArray = new JSONArray();
while (x.hasNext()) {
String key = (String) x.next();
jsonArray.put(jsonObject.get(key));
}
Toast.makeText(RolesActivity.this,jsonArray.toString(), Toast.LENGTH_LONG).show();
Log.d("jsonarray",jsonArray.toString());
}
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(RolesActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
}
You can get the JSONObject's keys list by calling JSONObject.keys() (as Iterator), or JSONObject.names() (as JSONArray)
After that you can iterate through the keys, and get each key's value by using JSONObject.getString(key)
First create a pojo class
private HashMap<String, String> parseResponse(){
String json = ""; // your json string
Gson gson = new Gson();
Response response = gson.fromJson(json, Response.class)
return response.getAssigned();
}
public class Response {
#SerializedName("Assigned")
private HashMap<String, String> assigned;
public HashMap<String, String> getAssigned() {
return assigned;
}
}
than parse with Gson library. You can read key and values from assigned Hashmap.

How to parse JSONArray with variable key (GSON)?

My json is :
{"array":[{"US":"id_123"},{"UK":"id_112"},{"EN":"id_1112"}...]}
My classes are:
class LocaleResponce implements Serializable{
#SerializedName("array")
List<Locale> array;
}
class Locale implements Serializable{
#SerializedName("title")
String title;
#SerializedName("id")
String id;
}
I'm tried to make this:
Gson gson = new Gson();
Type type = new TypeToken<LocaleResponce >(){}.getType();
LocaleResponce response = gson.fromJson(cacheJsonObject.toString(), type);
it doesn't work or is it an issue of server?
It can be achieved by creating custom JsonDeserializer.
Your deserializer class will look something like
public class CityListDeserializer implements JsonDeserializer<List<City>>{
#Override
public List<City> deserialize(JsonElement element, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<City> cityList = new ArrayList<>();
JsonObject parentJsonObject = element.getAsJsonObject();
Map.Entry<String, JsonElement> entry = parentJsonObject.entrySet().iterator().next();
Iterator<JsonElement> iterator = entry.getValue().getAsJsonArray().iterator();
City city;
while (iterator.hasNext()){
JsonObject cityJsonObject = iterator.next().getAsJsonObject();
for(Map.Entry<String, JsonElement> entry1 : cityJsonObject.entrySet()){
city = new City();
city.cityName = entry1.getKey();
city.id = entry1.getValue().toString();
cityList.add(city);
}
}
return cityList;
}
}
You can use it with
try {
JSONObject object = new JSONObject("{\"array\":[{\"US\":\"id_123\"},{\"UK\":\"id_112\"},{\"EN\":\"id_1112\"}]}");
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(new TypeToken<ArrayList<City>>() {}.getType(), new CityListDeserializer());
Gson gson = builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
List<City> cityList = gson.fromJson(String.valueOf(object), new TypeToken<ArrayList<City>>() {}.getType());
} catch (JSONException e) {
e.printStackTrace();
}
Your City class will be
public class City {
String cityName;
String id;
}
You can generate classes for Json using websites like http://www.jsonschema2pojo.org/ etc in your case the array array variable, does not have an array of homogeneous objects {"US":"id_123"},{"UK":"id_112"},{"EN":"id_1112"} these are all objects of different DataTypes because, the parameter keys are different, so for parsing this you cannot use a Pojo. The parameters vary from UK US EN etc, the solution here is either to ask the person who is developing the api to send Json that is Consistent, the array that you have received is not type safe, if you want to use this in Java you have to write lots of lines of code. For example you can get the value of the parameter "UK" like this
cacheJsonObject.get("array").getAsJsonArray().get(1).get("UK").getAsString();
This would return the value id_112 for instance.

Parsing JSON file in android

how to parse something like this in JSON ?
{"nodes":
{"0":
{"node":{"id":"13970","name_ar":"\u0623\u062f\u0647\u0645","name_en":"Adham","bio_ar":""}},
"1":
{"node":{"id":"14033","name_ar":"aa","name_en":"Ahmed Shaalan","bio_ar":""}}}
Its not an array its more than one object, any help please ?
You can retrieve them using JSONObject. This is a very simple example, and only parses the id out of one node:
JSONObject object = new JSONObject(myJsonString);
JSONObject nodes = object.getJSONObject("nodes");
JSONObject zero = nodes.getJSONObject("0");
JSONObject myNode = zero.getJSONObject("node");
String id myNode = myNode.getString("id");
Android contains native JSON parser - it is good for small amount of data (look into package org.json ) . If you have more data to parse, some pull parser like GSON will be better.
You need to create first a class with all the variables inside the JSON. Something like this:
import java.util.HashMap;
public class NodesClass { // Create a new class called NodesClass
public Nodes nodes; // Create a new public class
public class Nodes {
public HashMap<String, InnerObject> nodes;
}
public class InnerObject {
public Node node;
public class Node {
public int id;
public String name_ar, name_en, bio_ar;
}
}
}
Ant then you need to retrieve the data. E.g something like this:
NodesClass ndes = new Gson().fromJson(stringNodes, NodesClass.class);
int[] id = new int[11];
for (int numNodes = 0; numNodes < maxNumNodes; numNodes++)
{
try {
id[numNodes] = ndes.nodes.get(String.valueOf(numNodes)).node.id;
} catch (NullPointerException n) { break; }
}
I hope it help you.
Use org.json.JSONObject class:
jObject = new JSONObject(jString);
JSONObject nodesObject = jObject.getJSONObject("nodes");
ArrayList<JSONObject> objects = new ArrayList<JSONObject>();
for( int i=0; i<10; i++)
{
objects.add(nodesObject.getJSONObject(""+i);
}
String name = objects.get(0).getJSONObject("node").getString("name_ar");
...

Categories

Resources