Wrong serialization JSON in String field - android

I'm developing app using QuickBlox services. I have String field with JSON in content. This is my JSON:
{"answers":[[{"name":"first"}],[{"name":"second"}],[{"name":"third"}],[{"name":"fourth"}],[{"name":"fifth"}],[{"name":"sixth"}]]}
Here is problem. When I want to get my field with JSON from QBCustomObject, it is serialized to this (without quotes and square braces):
[{
answers :
{
name : first
},
{
name : second
},
{
name : third
},
{
name : fourth
},
{
name : fifth
},
{
name : sixth
}
}]
What can I do in this situation?
I found in QBCustomObjectDeserializer class that code:
if(value.contains("[")) {
String[] values2 = value.replace("[", "").replace("]", "").replace("\"", "").split(",");
Can I change rules of deserialization in QuickBlox SDK? Can I use my own deserializer?
Anyone can help resolve my problem please?

Fixed in development branch
https://github.com/QuickBlox/quickblox-android-sdk/tree/development
will be rolled out in our next upcoming release

Related

JsonArray as empty string parsing issue with retrofit

I have a json in which 1 key is coming as jsonArray if it has data otherwise it is coming as empty string. It is giving error while parsing in gson with retrofit.
"section": "Technology",
"subsection": "",
"title": "Depiction of Amazon Stirs a Debate About Work Culture",
"abstract": "Details of working conditions at Amazon led to a response from employees, relatives and friends.",
"url": "http://www.nytimes.com/2015/08/19/technology/amazon-workplace-reactions-comments.html",
"byline": "By THE NEW YORK TIMES",
"item_type": "Article",
"updated_date": "2015-08-18T07:35:33-5:00",
"created_date": "2015-08-18T07:35:35-5:00",
"published_date": "2015-08-19T04:00:00-5:00",
"material_type_facet": "News",
"kicker": "",
"des_facet": [
"Workplace Environment"
],
"org_facet": [
"Amazon.com Inc"
],
"per_facet": "",
"geo_facet": "",
des_facet , org_facet, per_facet, geo_facet are jsonArray but you can see that 2 are not having data so coming as empty string.
How to handle this scenario with retrofit +gson.
Json format can't be changed here at server.
is there any way I can achieve it in android?
Ok so there are two option you can solve this
Option 1:
JSON which I used as a example
"des_facet": [
"Workplace Environment"
],
"org_facet": [
"Amazon.com Inc"
],
"per_facet": ["Akshay"],
"geo_facet": ""
In your model class convert those variable to Object type
#Expose
#SerializedName("geo_facet")
private Object geo_facet;
#Expose
#SerializedName("per_facet")
private Object per_facet;
then where you want to set data do the following
if (model != null)
{
if (model.getGeo_facet() != null || model.getGeo_facet() != "")
{
Object arr = model.getGeo_facet();
}
if (model.getPer_facet() !=null || model.getPer_facet()!= "")
{
Object arr = model.getPer_facet();
if (arr!=null && arr.toString().length()>0)
{
arr = arr.toString();
Log.d("akshay","arr= "+arr);
//Do your Stuff or Set data
}
}
}
This is the output= 08-11 16:51:29.830 17951-17951/com.android.example
D/akshay: arr= [Akshay]
Option 2:
Follow this which is a little bit complex
Option 3:
Write own custom Parsing like this and Handle your response accordingly
a json can have a single structure. From the code it is clear that the key is given with 2 types of data
Ideally, it should not give "" when no items. It should give null
Please change the data
If no items,
"des_facet"=null // this is the change on server side. No need to change it on app side
If it has items
"des_facet"=[
"Workplace Environment"
]
instead of
If no items,
"des_facet"=""
If it has items
"des_facet"=[
"Workplace Environment"
]
You can use AutoValue with gson plugin and mark the field as nullable which will notify the Autovalue to make this field optional.
AZs an example this is how you do it:
#AutoValue
public abstract class NewsResponse{
public static TypeAdapter<NewsResponse> typeAdapter(Gson gson){
return new AutoValue_NewsResponse.GsonTypeAdapter(gson);
}
#SerializedName("api_status")
public abstract String apiStatus();
#SerializedName("api_text")
public abstract String success();
#Nullable
#SerializedName("errors")
public abstract ErrorDetails errorDetails();
#SerializedName("news")
public abstract List<NewsDetails> newsDetails();
}
you must import both of them see more info about importing at: AutoValue and AutoValue Gson Plugin

Firebase add item to array dynamically

I am trying to make some kind of comments using Firebase for Android.
Just have one question, are there any way to add new items to array?
For example, if I have such kind of object
If I am trying to push, it will convert it to map
And I don't want to overwrite this object each time, because I will have multiuser support and it will fail at some point.
And I am trying to do it as a List to do not create DataTransferObjects for my models, and to support auto parsing using firebase.
Thanks! If there will be no ideas will go with creating Maps, actually.
My ObjectModel:
public class Company implements Parcelable {
private String id;
private String name;
private String description;
private List<Comment> comments;
}
Code for pushing item:
final DatabaseReference ref = companiesRef.child(companyId).child(NODE_COMMENTS).push();
return Single.create(e -> ref.setValue(comment)
.addOnCompleteListener(task -> {
e.onSuccess(task.isSuccessful());
}));
This is how it works, look at the example below I have stored "0" as my first commentID and "1" as my second commentID. As you can see, I stored the lastCommentID as the commentID for the last comment in the lists.
{
"comments": {
"0": {
"text": "mycomment",
"time": "142351516"
},
"1": {
"text": "secondcomment",
"time": "153426564"
}
}
"lastCommentId": "1"
}
So whenever you want to add new comment to the firebase you have to retrieve the lastCommentID first as a string and convert it to integer(E.g. 1) then add 1 to the value(E.g. 2) so that when you save the next comment it won't override the previous version.
Note that you have replace lastCommentID each time you add comment to the database.
{
"comments": {
"0": {
"text": "mycomment",
"time": "142351516"
},
"1": {
"text": "secondcomment",
"time": "153426564"
},
"2": {
"text": "thirdcomment",
"time": "153426564"
}
}
"lastCommentId": "2"
}
You do not need to have a Model Class to write in Firebase, you can parse a JSON to Java Objects dinamically with Jackson and push it into Firebase.
You can parse a JSON as Java Objects with Jackson
. For example you can obtain: Object, List, Hashmap, Integer, String,
etc. without POJO classes.
To see more please visit this answer

(Android) Java: JSON Parsing

I found a lot of tutorials here, how to parse JSON Data of an JSON Array.
But my JSON File is a little bit complicate (for me). It has the following structure:
JSON File (excerpt)
{
"data": {
"schedule_id": {
"12": {
"name": "CP",
"d_id": [
"7"
]
},
"17": {
"name": "WT",
"d_id": [
"88",
"14"
]
}
}
}
}
Java Code (excerpt)
Info: I've parsed the json into "json" using HTTP GET in another Activity.
JSONObject dataJsonData = json.getJSONObject("data").getJSONObject("schedule_id");
Now I would parse through the ids using a "for"-loop:
ArrayList<String> parsedNameList = new ArrayList<String>();
for (int i = 0; i < idontknow; i++) {
String s = new Integer(i).toString();
parsedNameList.add(dateJsonData.getJSONObject(i).getString("name"));
}
This would add each value of "name" to the ArrayList.
But there are 2 problems:
1. The "schedule_id"s are messed up and incomplete. For example, there is no id "0" and, like in given json, the ids "13, 14, 15, 16" are missing.
2. The "schedule_id"s will be changed every day and will be mixed.
So I don't think, that I can use the predefined integer "i" because some integers aren't a "schedule_id". I could use this loop and would ignore empty entries in the ArrayList, but the JSON contains more than 200 ids - I think it would be more efficient, if there is another way to parse through this json.
I found some informations of the getJSONArray method, but the "d_id"s are Arrays - not the "schedule_ids".
Does anyone has an idea? Is there maybe a placeholder for the parameter of the getString method?
PS: Excuse my english, I'm from germany :)
I think this should work
Iterator keys = dataJsonData.keys();
while(keys.hasNext()) {
// loop to get the dynamic key
String currentDynamicKey = (String)keys.next();
// get the value of the dynamic key
String currentDynamicValue = dataJsonData .getString(currentDynamicKey);
parsedJsonList.add(currentDynamicValue );
}
Source: How to parse a dynamic JSON key in a Nested JSON result?
According to your context, it is better to change the json structure,if you have access to web service.
Request for json structure to be like this,
{
"data":{
"schedule":[
{
"id":12,
"name":"CP",
"d_id":[
"7"
]
},
{
"id":12,
"name":"CP",
"d_id":[
"7",
"88"
]
},
{
"id":200,
"name":"AT",
"d_id":[
"7",
"88"
]
}
]
}
}
Otherwise too much iteration can slow down you CPU.

Why does ASP MVC create a JSON format Android doesn't like?

I have a very basic ASP MVC application exposing a static list of publications (see code and result below).
Code:
public JsonResult Index()
{
List<Publication> list = new List<Publication>() {
new Publication() { Id = 1, Name = "War and Peace" },
new Publication() { Id = 2, Name = "Harry Potter" },
new Publication() { Id = 3, Name = "Cat in the Hat" }
};
return this.Json(list, JsonRequestBehavior.AllowGet);
}
Result:
[{"Id":1,"Name":"War and Peace"},{"Id":2,"Name":"Harry Potter"},{"Id":3,"Name":"Cat in the Hat"}]
When I attempt to consume it in Android I get the following error:
04-15 12:00:57.331: W/System.err(209): org.json.JSONException: A JSONObject text must begin with '{' at character 1 of [{"Id":1,"Name":"War and Peace"},{"Id":2,"Name":"Harry Potter"},{"Id":3,"Name":"Cat in the Hat"}]
I can remove the starting [ and ending ] and it stops the error from appearing. The other option is to put the { publications: logic at the beginning of the android code, but that seems like it should already be there.
How can I update the code in the MVC application to produce a "ready to be consumed" version of JSON?
Any help is greatly appreciated.
First, you shouldn't modify your json string when received, because it may mess up with the parsing.
Second, your Json string is in array format because it starts with [ and ends with ]. So, instead of using JSONObject, you should use JSONArray.
I recommend to use GSON. It's simple to use, fast and accurate.

Most Efficient Way to Parse JSON Using Android

I've written some code to parse the Google Distance Matrix JSON response received by my Android program. The only piece of data I'm interested in is in the "distance" "value" node.
My code works, but it seems like there must be an easier way to do this. The distance value node is nested pretty deep inside the JSON, but is it really necessary to go through every layer of the JSON to get to the field you want?
Here's my JSON response:
{
"destination_addresses" : [
"5660 Baltimore National Pike, Ingleside Shopping Center, Catonsville, MD 21228, USA"
],
"origin_addresses" : [ "Hilltop Cir, Baltimore, MD 21250, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "3.1 mi",
"value" : 4922 <--THE FIELD I WANT TO EXTRACT
},
"duration" : {
"text" : "11 mins",
"value" : 666
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
And here is the code I used to pull out the distance value:
private double extractDistance(JSONObject json) {
JSONArray rowsArray = null;
double distanceInMiles = -1;
try {
// Getting Array of Distance Matrix Results
rowsArray = json.getJSONArray("rows");
JSONObject rowsObject = rowsArray.getJSONObject(0);//only one element in this array
JSONArray elementsArray = rowsObject.getJSONArray("elements");
JSONObject elementsObject = elementsArray.getJSONObject(0);//only one element in this array
JSONObject distanceObject = elementsObject.getJSONObject("distance");
distanceInMiles = (distanceObject.getDouble("value"))/1609.344; //distance in meters converted to miles
}
catch (JSONException e) {
e.printStackTrace();
}
return distanceInMiles;
}
Thanks!
I recommend you GSON (http://code.google.com/p/google-gson/) which parse the JSON text into a java class instance, and can convert the class instance to JSON text
Jackson is another good third party parser http://jackson.codehaus.org/. Looks like there's a comparison here, http://www.cowtowncoder.com/blog/archives/2009/09/entry_326.html.
Here's an example traversing using a tree, not sure if it qualifies as easier then what you are already doing, http://wiki.fasterxml.com/JacksonTreeModel
Unless you want to go into writing a custom regular expression to search the json string, yes that's going to be the best way of accessing it (and the easiest). Is there a reason you feel you need to access it 'more efficiently'?
If you are willing to include a third party library you might check out http://code.google.com/p/json-path/ .
I know what you feel right now, I had / have same issues with JSON parsing on android where we dont have #getValueforKey kind of features which is embedded on iOS, Even its so obivious google should realize it now, But there is good work done on Gson lib., look for Google Gson Here for easy way to parse json
Here is nice tute : Gson tute

Categories

Resources