I am using the Retrofit Library in Android to read the JSON data.
I want to only read the country names from the below JSON i.e just the value. Is it possible to read such JSON data using Retrofit Library?
{
"China": ["Guangzhou", "Fuzhou", "Beijing"],
"Japan": ["Tokyo", "Hiroshima", "Saitama", "Nihon'odori"],
"Thailand": ["Bangkok", "Chumphon", "Kathu", "Phang Khon"],
"United States": ["Mukilteo", "Fairfield", "Chicago", "Hernando", "Irving", "Baltimore", "Kingston"],
"India": ["Bhandup", "Mumbai", "Visakhapatnam"],
"Malaysia": ["Pantai", "Kuala Lumpur", "Petaling Jaya", "Shah Alam"]
}
List<String> list = new ArrayList<>();
Iterator<String> iter = json.keys();
while (iter.hasNext()) {
String key = iter.next();
list.add(key);
try {
Object value = json.get(key);
} catch (JSONException e) {
// Something went wrong!
}
}
Log.d("TAG",list.toString());
You can use HashMap<String,ArrayList<String>> as retrofit result obj and get the keys.
or just get it with string then cast it to hasmap
val typeToken: Type = object : TypeToken<HashMap<String, ArrayList<String>>>()
{}.type
val result = Gson().fromJson<HashMap<String, ArrayList<String>>>(tmp, typeToken)
then you can iterate trough the keys.
for example :
public class Country{
private List<String> name;
}
An associative array translates to a Map in Java:
Map<String, Country > countries = new Gson().fromJson(json, new TypeToken<Map<String, Country >>(){}.getType());
in retrofit just add to model class:
#Expose
private Map<String, Country> result;
Related
I have a nested JSON array from which I need to retrieve values of all Usernames nested within Friends.
{
"Friends": [
{"Username": "abc"},
{"Username": "xyz"}
]
}
After I get all the usernames, I want to store it in a List that I will use with an adapter and ListView.
FriendList.java:
public class FriendList
{
#SerializedName("Username")
private String username;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
}
This is the code that I have written so far:
if (httpResult != null && !httpResult.isEmpty()) //POST API CALL
{
Type listType = new TypeToken<List<FriendList>>() {}.getType();
List<FriendList> friendList = new Gson().fromJson(httpResult, listType);
FLCustomAdapter adapter = new FLCustomAdapter(getActivity(), friendList);
mainFriendsListView.setAdapter(adapter);
}
However, an error occurs: Failed to deserialize Json object.
Please suggest, what additions/changes should be made to it, so that I can retrieve nested JSON values into a list?
First of all, You have to understand the strucure of this Json.
You can see, it contains
1 . A json object
2 . This json object contains a json array which can include several different json objects or json arrays.
In this case, it contains json objects.
Parsing:
Get the Json Object first
try{
JSONObject jsonObject=new JSONObject(jsonResponse);
if(jsonObject!=null){
//get the json array
JSONArray jsonArray=jsonObject.getJSONArray("Friends");
if(jsonArray!=null){
ArrayList<FriendList> friendList=new ArrayList<FriendList>();
//iterate your json array
for(int i=0;i<jsonArray.length();i++){
JSONObject object=jsonArray.getJSONObject(i);
FriendList friend=new FriendList();
friend.setUserName(object.getString(Username));
friendList.add(friend);
}
}
}
}
catch(JSONException ex){
ex.printStackTrace();
}
hope, it will help you.
Solution with GSON.
You need to two class to parse this.
FriendList and UsernameDao.
public class UsernameDao {
#SerializedName("Username")
private String username;
//get set methods
}
Simple Json Parsing would be like this
JSONObject params=new JSONObject(httpResult);
JSONObject params1=params.getJsonObject("Friends");
JsonArray array=params1.getJsonArray();
for(int i=0;i<array.length();i++)
{
String userName=array.getJsonObject(i).getString("UserName");
// Do whatever you want to do with username
}
Following code works good without any use of GSON , Please try .
String jsonString = "Your Json Data";
JSONObject jsonRootObject = new JSONObject(jsonString );
JSONArray friendsArray = jsonRootObject .getJSONArray("Friends");
ArrayList<FriendList > friendsList = new ArrayList<FriendList >();
for(int friendsLen = 0 ;friendsLen < friendsArray .length() ; friendsLen ++){
FriendList userNameObj = new UserName();
JSONObject jsonObj = jsonRootObject.getJSONObject(friendsLen ) ;
String Username = jsonObj.getString("Username");
userNameObj .setUserName(Username );
friendsList .add(userNameObj );
}
Now friendsList the list which you want .
List<FriendList> friendList = new Gson().fromJson(httpResult, listType);
This cannot work because it expects your whole JSON document to be just an array of FriendList element (by the way, why "FriendList"?): [{"Username": "abc"},{"Username": "xyz"}] -- this is what can be parsed by your approach.
The easiest solution to fix this (apart from harder to implement but more efficient streamed reading in order to peel of possible unnecessary properties) is just creating a correct mapping:
final class Wrapper {
#SerializedName("Friends")
final List<Friend> friends = null;
}
final class Friend {
#SerializedName("Username")
final String username = null;
}
Now deserialization is trivial and you don't have to define a type token because Gson has enough information for the type from the Wrapper.friends field:
final Wrapper wrapper = gson.fromJson(response, Wrapper.class);
for ( final Friend friend : wrapper.friends ) {
System.out.println(friend.username);
}
Output:
abc
xyz
Change List<FriendList> friendList = new Gson().fromJson(httpResult, listType);
to
FriendList friends = new Gson().fromJson(httpResult, listType);
List<Friend> friends = friends.list;
Updated FriendList.java as mentioned below
FriendList.java
public class FriendList
{
#SerializedName("Friends")
public List<Friend> list;
}
Friend.java
public class Friend
{
#SerializedName("Username")
private String username;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
}
Hello friends i have following JSON foramt
{
"Communities": [],
"RateLog": { "83": 5,"84": 4, "85": 5,"92": 5,"93": 4,"94": 5,"95": 5,"97": 5,"99": 4,"100": 5,"102": 5,"103": 5,"104": 5,"105": 5,"106": 5,"108": 4,"109": 4,"110": 4,"111": 5,"112": 4,"113": 4,"114": 4,"115": 5,"116": 5,"117": 5,"118": 4,"119": 5, "120": 5,"121": 4,"122": 5,"123": 4,"124": 4,"125": 4,"126": 5, "142": 5,"1150": 4, "1151": 4,"1152": 4, "1153": 4,"1154": 4, "1155": 4,"1156": 4, "1158": 5}
}
so how can i parse it any idea?
You can turn it into legal JSON by enclosing it in braces. So if you have the string:
var badJSON = '"RateLog" : { "1156": 4, ... }';
You can do this:
var goodJSON = '{' + badJSON + '}';
var parsed = JSON.parse(goodJSON);
EDIT: The above answer was before your edit. With the new format, the string is valid JSON, so simply call JSON.parse() and pass the string to get the corresponding object structure.
You must improve your json format like this :
"RateLog":[
{
id1:1156
id2:4
{
id1:1155
id2:4
}
{
id1:1155
id2:4
}
..]
JSONObject json = new JSONObject(jsonString);
JSONArray array = json.getJSONArray("Communities");
for (int i = 0; i < array.length(); i++) {
// do stuff
}
JSONObject rateJson = json.getJSONObject("RateLog");
rateJson.getInt("83"); //Will return 5
.
.
.
for more got through this tutorial
http://www.mkyong.com/java/json-simple-example-read-and-write-json/
You can use Google's Gson library to parse your response.
Using POJO class
String jsonString = "Your JSON string";
Pojo pojo = new Gson().fromJson(jsonString, Pojo.class);
class Pojo {
ArrayList<String> Communities;
HashMap<String, Integer> RateLog;
//Setters and Getters
}
Without using POGO class
Gson gson = new Gson();
String jsonString = "Your JSON string";
JsonObject jsonObj = gson.fromJson(jsonString, JsonElement.class).getAsJsonObject();
HashMap<String, Integer> RateLog = gson.fromJson(jsonObj.get("RateLog").toString(), new TypeToken<HashMap<String, Integer>>(){}.getType());
You can iterate through RateLog HashMap to get key, value pairs.
How to parse below Json Response with google Gson.?
{
"rootobject":[
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
},
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
},
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
},
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
}
]
}
I'd create objects to "wrap" the response, such as:
public class Response {
#SerializedName("root_object")
private List<YourObject> rootObject;
//getter and setter
}
public class YourObject {
#SerializedName("id")
private String id;
#SerializedName("name")
private String name;
#SerializedName("subtitle")
private String subtitle;
//... other fields
//getters and setters
}
Note: use #SerializedName annotation to follow naming conventions in your Java attribute while matching the names in the JSON data.
Then you just parse the JSON with your Reponse object, like this:
String jsonString = "your json data...";
Gson gson = new Gson();
Response response = gson.fromJson(jsonString, Response.class);
Now you can access all the data in your Response object using getters and setters.
Note: your Response object may be used to parse different JSON responses. For example you could have JSON response that don't contain the id or the subtitle fields, but your Reponseobject will parse the response as well, and just put a null in this fields. This way you can use only one Responseclass to parse all the possible responses...
EDIT: I didn't realise the Android tag, I use this approach in a usual Java program, I'm not sure whether it's valid for Android...
You can try this hope this will work
// Getting Array
JSONArray contacts = json.getJSONArray("rootobject");
SampleClass[] sample=new SampleClass[contacts.length]();
// looping through All
for(int i = 0; i < contacts.length(); i++){
JSONObject c = contacts.getJSONObject(i);
// Storing each json item in variable
sample[i].id = c.getString("id");
sample[i].name = c.getString("name");
sample[i].email = c.getString("subtitle");
sample[i].address = c.getString("key1");
sample[i].gender = c.getString("key12");
sample[i].gender = c.getString("location");
sample[i].gender = c.getString("key13");
sample[i].gender = c.getString("key14");
sample[i].gender = c.getString("key15");
sample[i].gender = c.getString("result_status");
}
I have been using GSON library to parse all the json string and get a JSON object.
But now I need to parse is like this:
{
"status":1,
"info":[
{
"\u5a31\u4e50":"\u51b7\u76d8,\u9ad8\u811a\u676f,\u6211\u7684\u7cd6\u679c\u5c4b,\u670d\u52a1\u4e1a\u6d88\u8d39\u52b5"
},
{
"\u7f8e\u5986":"\u4e2a\u62a4|\u5316\u5986#\u9762\u90e8\u62a4\u7406,\u4e2a\u4eba\u536b\u751f,\u8eab\u4f53\u62a4\u7406,\u9999\u6c34\u9999\u6c1b,\u6c90\u6d74|\u7f8e\u53d1\u7528\u54c1,\u5f69\u5986,\u7cbe\u6cb9SPA,\u773c\u90e8\u62a4\u7406,\u78e8\u7802\u53bb"
},
{
"\u8863\u670d":"\u670d|\u9970|\u978b|\u5e3d#\u670d\u88c5,\u978b\u9774,\u5185\u8863,\u914d\u9970,\u536b\u8863,\u4f11\u95f2\u88e4,T\u6064,\u88d9\u5b50,\u886c\u886b,\u9488\u7ec7\u886b,\u5a74\u5e7c\u513f\u670d\u9970"
}
],
"total":3
}
The key fields are dynamic, so I don't know how to write a model class to read this.
How would you like your model class to look?
status and total would probably be int, so that only leaves info.
As an experiment, just add a field Object info and see how Gson would set it to an ArrayList<LinkedHashMap<String, String>> -- ugly and hard to access by key, but all the data is there. Given that information, the fastest way to model a class would be:
class Something {
int status;
List<Map<String, String> info;
int total;
}
If you have control over how that JSON is generated, I suggest changing the structure of info from an array of objects [{a:b},{c:d},{e:f}] to just an object {a:b,c:d,e:f}. With this, you could just map it to a Map<String, String> with all the benefits like access by key, keys() and values():
class Something {
int status;
Map<String, String> info;
int total;
}
If you want the latter model class without changing the JSON format, you'll have to write a TypeAdapter (or JsonDeserializer if you're only interested in parsing JSON, not generating it from your model class).
Here's a JsonDeserializer hat would map your original info JSON property to a plain Map<String, String>.
class ArrayOfObjectsToMapDeserializer
implements JsonDeserializer<Map<String, String>> {
public Map<String, String> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
Map<String, String> result = new HashMap<String, String>();
JsonArray array = json.getAsJsonArray();
for (JsonElement element : array) {
JsonObject object = element.getAsJsonObject();
// This does not check if the objects only have one property, so JSON
// like [{a:b,c:d}{e:f}] will become a Map like {a:b,c:d,e:f} as well.
for (Entry<String, JsonElement> entry : object.entrySet()) {
String key = entry.getKey();
String value = entry.getValue().getAsString();
result.put(key, value);
}
}
return result;
}
}
You need to register this custom JsonDeserializer similar to this:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<Map<String, String>>() {}.getType(),
new ArrayOfObjectsToMapDeserializer());
Gson gson = builder.create();
Note that this registers the custom deserializer for any Map<String, String> regardless in what class it is encountered. If you don't want this, you'll need to create a custom TypeAdapterFactory as well and check the declaring class before returning and instance of the deserializer.
Here goes a solution, which does not requires to make a JsonDeserializer.
All you can create is a JsonElement in a map Map.Entry<String, JsonElement>and use a for loop to iterate over the entries
//parsing string response to json object
JsonObject jsonObject = (JsonObject) new JsonParser().parse(jsonString);
//getting root object
JsonObject dateWiseContent = jsonObject.get("rootObject").getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : dateWiseContent.entrySet()) {
//this gets the dynamic keys
String dateKey = entry.getKey();
//you can get any thing now json element,array,object according to json.
JsonArray jsonArrayDates = entry.getValue().getAsJsonArray();
}
read more here
I am using GSON to deserialize JSON like this:
Type mapType = new TypeToken<Map<Integer, MyClass> >() {}.getType(); // define generic type
Map<Integer, MyClass> jsData= gson.fromJson(r, mapType);
MyClass is:
public class MyClass{
private String status;
private String mObjectType; //Where mObjectType = Type1 = Type2 = Type3 = Type4
//some more value + getters/setters
}
JSON response is:
{
128: {
status: someValue,
mObjectType: Type1
},
124: {
status: someValue,
mObjectType: Type3
},
123: {
status: someValue,
mObjectType: Type2
}
}
Thereafter I have Map with JSON data and I can iterate through Map. I want sort this Map by value mObjectType for insert into ListAdepter in a certain order, there ObjectType will be header each section.
How can I sort this map on mObjectType? Through iterator I can get all of values for current key. Or will it be better implement a custom Comparator?
upd
I did it like:
Iterator i = jsData.entrySet().iterator();
while (i.hasNext()){
Map.Entry iLookObj = (Map.Entry)i.next();
MyClass temp = (MyClass)iWatchObj.getValue();
if(temp.getObjectType().equals("ObjectType1")){
ObjectType1.add(temp);
} else if (temp.getObjectType().equals("ObjectType2")){
ObjectType2.add(temp);
}else if (temp.getObjectType().equals("ObjectType3")){
ObjectType3.add(temp);
}
}
Do not know yet how differently do it.