Deserialize a JSON that has a key variable jackson map ObjectMapper - android

JSON:
{
"id": "1704",
"title": "Choice of Drink",
"multiselect": 0,
"maximum_selection": 1,
"ac_items": 1,
"Choice of Drink": [{
"id": "8151",
"name": "Lemon Ice Tea",
"price": 0,
"orig_price": 0
}, {
"id": "8152",
"name": "Fresh Lime",
"price": 0,
"orig_price": 0
}]
}
The problem is that the key "Choice of Drink" is a variable.How can I put this in a #JsonProperty, when I don't have the name?

You can use Jackson's #JsonAnySetter annotation to direct all variable keys to one method and there you can assign/handle them as you wish:
public class Bar
{
// known/fixed properties
public String id;
public String title;
public int multiselect;
public int maximum_selection;
public int ac_items;
// unknown/variable properties will go here
#JsonAnySetter
public void setDrinks(String key, Object value)
{
System.out.println("variable key = '" + key + "'");
System.out.println("value is of type = " + value.getClass());
System.out.println("value toString = '" + value.toString() + "'");
}
}
in the case of the sample input, the output is:
variable key = 'Choice of Drink'
value is of type = class java.util.ArrayList
value toString = '[{id=8151, name=Lemon Ice Tea, price=0, orig_price=0}, {id=8152, name=Fresh Lime, price=0, orig_price=0}]'

Try this
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String,Map<String, String>>>() {}.getType();
Map<String,Map<String, String>> map = gson.fromJson(jsonString, mapType);

Related

Couldn't get "name" value from json via Retrofit

I have a problem for getting "ad" value from mysql database.
Here is my listele.php code to get a json format including values.
<?php
//If the values are not blank
//Connecting to our database by calling dbConnect script
include('connection.php');
Class Kullanici{
public $id = "";
public $ad = "";
public $soyad = "";
}
$kl = new Kullanici();
$sql = "SELECT * FROM kullanici";
$list = mysqli_query($conn,$sql);
$resultFromSql = mysqli_num_rows($list);
$sayac = 0;
echo("[");
while($result = mysqli_fetch_assoc($list)){
$sayac = $sayac + 1;
$kl->id = $result["id"];
$kl->ad = $result["ad"];
$kl->soyad = $result["soyad"];
echo json_encode($kl,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
if($resultFromSql != $sayac){
echo(",");
}
}
echo("]");
?>
When I run the code snippet, I get the json format
[{ "id": "27", "ad": "Aslı", "soyad": "Şafak" },{ "id": "29", "ad": "Ali", "soyad": "Ak" },{ "id": "30", "ad": "Ersin", "soyad": "Demir" },{ "id": "31", "ad": "Sercan", "soyad": "Demirbaş" }]
When I get these values from json format to insert all them into the listview, "ad" value is null but others have their values.
kullanicilist = new ArrayList<>();
Call<List<Kullanici>> x = Manager.getInstance().goster();
x.enqueue(new Callback<List<Kullanici>>() {
#Override
public void onResponse(Call<List<Kullanici>> call, Response<List<Kullanici>> response) {
Log.i(LOG,"istek | onResponse is working");
if (response.isSuccessful()) {
kullanicilist = response.body();
Log.i(LOG,"istek | kullanicilist : " + kullanicilist.toString());
adp = new KullaniciAdapter(kullanicilist, getApplicationContext(), MainActivity.this);
listView.setAdapter(adp);
}
}
#Override
public void onFailure(Call<List<Kullanici>> call, Throwable t) {
Log.i(LOG,"istek | onFailure is working");
Log.i(LOG,t.getMessage());
}
});
First Log statement in onResponse
I/com.example.dbtojson.activity.MainActivity: istek | kullanicilist : [Kullanici{id='27', isim='null', soyad='Şafak'}, Kullanici{id='29', isim='null', soyad='Ak'}, Kullanici{id='30', isim='null', soyad='Demir'}, Kullanici{id='31', isim='null', soyad='Demirbaş'}]
Data you get from server is
{ "id": "27", "ad": "Aslı", "soyad": "Şafak" }
Data you are printing in retrofit client is
Kullanici{id='27', isim='null', soyad='Şafak'}
Server is sending value "Asli" in key name ad. Your client has member variable isim which is a different key name, that's why it is not getting mapped.
In client,
Change your member variable name from isim to ad
OR
if you are using GSON then put annotation above it.
#SerializedName("ad")
String isim
This will map value of key ad to isim

Getting element of JSON object when key isn't the same [Android]

I want to learn a bit more about android and wanted to create an app that will track the price of cryptocurrencies. I choosed this API: https://www.cryptocompare.com/api/#introduction
My problem is the following: When I want to get the list of all the coin the JSON response looks like this:
{
"Response": "Success",
"Message": "Coin list succesfully returned!",
"BaseImageUrl": "https://www.cryptocompare.com",
"BaseLinkUrl": "https://www.cryptocompare.com",
"Data": {
"42": {
"Id": "4321",
"Url": "/coins/42/overview",
"ImageUrl": "/media/19984/42.png",
"Name": "42",
"CoinName": "42 Coin",
"FullName": "42 Coin (42)",
"Algorithm": "Scrypt",
"ProofType": "PoW",
"FullyPremined": "0",
"TotalCoinSupply": "42",
"PreMinedValue": "N/A",
"TotalCoinsFreeFloat": "N/A",
"SortOrder": "34"
},
"365": {
"Id": "33639",
"Url": "/coins/365/overview",
"ImageUrl": "/media/352070/365.png",
"Name": "365",
"CoinName": "365Coin",
"FullName": "365Coin (365)",
"Algorithm": "X11",
"ProofType": "PoW/PoS",
"FullyPremined": "0",
"TotalCoinSupply": "2300000000",
"PreMinedValue": "299000000",
"TotalCoinsFreeFloat": "N/A",
"SortOrder": "916"
},
(here is the URL I use (https://www.cryptocompare.com/api/data/coinlist/)
I want to keep all the informations about the coin (everything from "Data") but the key isn't the same.
How can I get those informations to create my differents coins?
Thank's in advance
You can use JSONObject#names() to get all the keys as JSONArray and loop the JSONArray.
JSONObject data = response.getJSONObject("Data");
JSONArray array = data.names(); // contains all the keys inside Data
// now loop the array
for (int i = 0; i < array.length(); i++ ) {
String key = array.getString(i); // 42 or 365 for your example code
JSONObject obj = data.getJSONObject(key); // contains the JSONObject of the key 42 or 365
}
Another way is to use JSONObject#keys() but that uses Iterator and hasNext() for iteration which is less performance efficient than the above normal for loop approach in Android.
The accepted answer is fine. I would like to show the way of parsing using Gson from your JSON. Here's how it can be parsed using Gson.
You need to have two classes.
Here's your APIResponse.java
public class APIResponse {
public String Response;
public String Message;
public String BaseImageUrl;
public String BaseLinkUrl;
public HashMap<String, DataObject> Data;
}
And the DataResponse class should look like
public class DataObject {
public String Id;
public String Url;
public String ImageUrl;
public String Name;
public String CoinName;
public String FullName;
public String Algorithm;
public String ProofType;
public String FullyPremined;
public String TotalCoinSupply;
public String PreMinedValue;
public String TotalCoinsFreeFloat;
public String SortOrder;
}
Now its pretty easy.
Type type = new TypeToken<APIResponse>(){}.getType();
APIResponse response = new Gson().fromJson(yourJsonString, type);
Now iterate the HashMap for getting the keys and corresponding values.
You can fetch all the keys and iterate as below
try {
JSONObject dataObj = obj.getJSONObject("Data"); //obj is the parent json object.
Iterator<?> keys = dataObj.keys();
while(keys.hasNext()) {
JSONObject coinObj = dataObj.getJSONObject(keys.next().toString());
}
} catch (JSONException e) {
e.printStackTrace();
}

Nested Json parsing using Gson

I have tried to parse this JSON using gson but I couldn’t.
Can anyone help me to parse this JSON using gson?
JSON:
{
"status": "ok",
"results": {
"favourites": [
{
"id": "UB3172",
"name": "Masdar Headquarters"
},
{
"id": "UB1438",
"name": "Guggenheim Abu Dhabi on Saadiyat Island"
},
{
"id": "UB4838",
"name": "Watani Residential Development in Abu Dhabi - 600 Villas and 48 Buildings"
},
{
"id": "UB4795",
"name": "Two Mosques in Mohammed Bin Zayed City"
},
{
"id": "UB1274",
"name": "2 Workers Residential City at Al Ain Industrial City"
}
]
}
}
I tried this one for JSON parser class:
public class ProjectList {
public String status;
public String results;
public class Favourites{
public String id;
public String name;
}
}
In MainActivit
Reader reader = new InputStreamReader(result);
Gson gson=new Gson();
List<ProjectList.Favourites> fav=new ArrayList<ProjectList.Favourites>();
fav=Arrays.asList(gson.fromJson(reader, ProjectList.Favourites.class));
Create a POJO class as follows
class MyResponse {
public String status;
public Result results;
public static class Favourites {
public String id;
public String name;
}
public static class Result {
public List<Favourites> favourites;
}
}
and pass it to gson as
MyResponse response = new Gson().fromJson(yourResponse, MyResponse.class);
idea is that maintain the hierarchy of key-value pairs with appropriate POJO's
You can generate your pojos here : http://www.jsonschema2pojo.org/
Sometimes gson cannot convert your objects from json. In this case you have to write your own deserializer and use it with gson builder.
Edit: If you use proguard before release your project (if you set proguard to change your pojos variable names) gson cannot match class variable names, json names so it cannot convert your objects. You have to add #SerializedName("your_variable_name") annotaion.
Try this way,hope this will help you to solve your problem.
String jsonRespone = "{\"status\":\"ok\",\"results\":{\"favourites\":[{\"id\":\"UB3172\",\"name\":\"Masdar Headquarters\"},{\"id\":\"UB1438\",\"name\":\"Guggenheim Abu Dhabi on Saadiyat Island\"},{\"id\":\"UB4838\",\"name\":\"Watani Residential Development in Abu Dhabi - 600 Villas and 48 Buildings\"},{\"id\":\"UB4795\",\"name\":\"Two Mosques in Mohammed Bin Zayed City\"},{\"id\":\"UB1274\",\"name\":\"2 Workers Residential City at Al Ain Industrial City\"}]}}";
String status;
ArrayList<HashMap<String,String>> favouritesList = new ArrayList<HashMap<String, String>>();
try{
JSONObject responseJson = new JSONObject(jsonRespone);
status = responseJson.getString("status");
JSONArray favouriteJsonArray = responseJson.getJSONObject("results").getJSONArray("favourites");
for (int i=0;i<favouriteJsonArray.length();i++){
HashMap<String,String> favourite = new HashMap<String, String>();
favourite.put("id",favouriteJsonArray.getJSONObject(i).getString("id"));
favourite.put("name",favouriteJsonArray.getJSONObject(i).getString("name"));
favouritesList.add(favourite);
}
System.out.print("status : "+status);
for (HashMap<String, String> favourite : favouritesList) {
System.out.print("id : "+favourite.get("id"));
System.out.print("name : "+favourite.get("name"));
}
}catch (Throwable e){
e.printStackTrace();
}

JSONObject parsing error when there is no value

I have a JSON which looks like this:
{
"notifications": {
"0": {
"id": "27429",
"uID": "6967",
"text": "Text 1"
},
"1": {
"id": "27317",
"uID": "6967",
"text": "Text 2"
},
"2": {
"id": "27315",
"uID": "6967",
"text": "Text 3"
},
"3": {
"id": "27314",
"uID": "6967",
"text": "Text 4"
},
"4": {
"id": "27312",
"uID": "6967",
"text": "Text 5"
}
}
}
I'm taking out "text" string from the response, for this my code looks like this:
JSONObject rootObj = new JSONObject(result);
JSONObject jSearchData = rootObj.getJSONObject("notifications");
int maxlimit = 4;
for (int i = 0; i < maxlimit; i++) {
JSONObject jNotification0 = jSearchData.getJSONObject("" + i + "");
String text = jNotification0.getString("text");
System.out.println("Text: " + text);
}
For now this works perfectly fine, I get all the 4 "text" in the logs.
Now, my problem is that when I get response from server with only 1 or 2 data, something like this:
{
"notifications": {
"0": {
"id": "27429",
"uID": "6967",
"text": "Only one text here"
}
}
}
Then my above logic fails, I get exception stating org.json.JSONException: No value for 1
How can I overcome this problem.
Any kind of help will be appreciated.
you can test if a key exists with rootObj.has("1") or use rootObj.optJSONObject("1");
the former returns true if this object has a mapping for name. The latter returns the value mapped by name if it exists and is a JSONObject, null otherwise.
Or you can interate through the keys inside rootObj, this way:
Iterator<String> keys = jSearchData.keys();
while (keys.hasNext()) {
String key = keys.next();
JSONObject jNotification0 = jSearchData.optJSONObject(key);
if (jNotification0 != null) {
String text = jNotification0.getString("text");
String uID = jNotification0.getString("uID");
String id = jNotification0.getString("id");
}
}
Edit: This is wrong, I read to fast and did not realize jSearchData was an object and not an array. But in my opinion if would make a lot more sense if it was in fact an array instead of an object.
There's no need to hard code the 4. Just take the length of the array and loop through it, like this:
for (int i = 0; i < jSearchData.length(); i++) {
JSONObject jNotification0 = jSearchData.getJSONObject("" + i + "");
String text = jNotification0.getString("text");
System.out.println("Text: " + text);
}

Json to java object android?

Can anyone please help me to convert this JSON to Java Object. I usually use GSON, but it seem this time it is not working for me. The problem is that I want to create an Object that contains
Class JsonGotText{
String status;
List<Object> result;
}
But all the Object in List is all difference properties... So I don know how to do to let Gson Map it correctly
{
"status": 0,
"result": {
"1346053628": {
"type": "default",
"decorated_time": 1346053628,
"guidOwner": 13716,
"friendGuid": 3264,
"action_type": "friend",
"summary": " is now a friend with ",
"annotation": null,
"group": ""
},
"1346051675": {
"type": "event",
"decorated_time": 1346051675,
"guidOwner": 90,
"title": null,
"action_type": "event_relationship",
"summary": "river:event_relationship:object:event",
"annotation": null,
"group": ""
},
"1346048488": {
"type": "event",
"decorated_time": 1346048488,
"guidOwner": 90,
"title": null,
"action_type": "event_relationship",
"summary": "river:event_relationship:object:event",
"annotation": null,
"group": ""
}
}
}
Try using
Class JsonGotText{
String status;
HashMap<String, Object> result;
}
If performance is not key criteria here. You better use 'JSONObject' without worrying the structure of JSON String.
Ideally, you should write a POJO. Say EventPOJO that has attributes same as as each result object holds and then make the Java class as
Class JsonGotText{
String status;
HashMap<String, EventPOJO> result;
}
you may have to use a type token see here, but will save your efforts later.
Update
It seems the sentence above sounds confusing. Here is clarification what I wanted EventPOJO to represent to. The EventPOJO will represents things like
{
"type": "event",
"decorated_time": 1346048488,
"guidOwner": 90,
"title": null,
"action_type": "event_relationship",
"summary": "river:event_relationship:object:event",
"annotation": null,
"group": ""
}
Update1 #LalitPoptani asked for exact working code. Here it is!
Here is an working example:
public class Test {
private static String json =
"{"+
"\"status\": 0,"+
"\"result\": {"+
"\"1346053628\": {"+
"\"type\": \"default\","+
"\"decorated_time\": 1346053628,"+
"\"guidOwner\": 13716"+
"},"+
"\"1346051675\": {"+
"\"type\": \"event\","+
"\"decorated_time\": 1346051675,"+
"\"guidOwner\": 90"+
"},"+
"\"1346048488\": {"+
"\"type\": \"event\","+
"\"decorated_time\": 1346048488,"+
"\"guidOwner\": 90"+
"}"+
"}" +
"}";
public static class Event{
String type;
Long decorated_time;
Integer guidOwner;
}
public static class JSON{
Integer status;
HashMap<Long, Event> result;
}
public static void main(String[] args){
Gson gson = new Gson();
System.out.println("JSON: " + json);
JSON j = gson.fromJson(json, JSON.class);
for(Entry<Long, Event> e: j.result.entrySet()){
System.out.println(e.getKey() + ": " + e.getValue().guidOwner);
}
}
}

Categories

Resources