How to parse a json fetched from Volley Android - android

Heres my code of Volley Fetching API Request How do i parse?
i wanted somethinf like : $response[0]
val sq = StringRequest(Request.Method.GET, url,
Response.Listener<String> { response ->
//print the response
Log.i("GoogleIO","Response is : $response")
}, Response.ErrorListener {
//Log the error
Log.i("GoogleIO","That din't work")
})
//Add the request to the RequestQueue
Volley.newRequestQueue(this).add(sq)

Lets suppose you have this json string in response
{
name: "John",
age: 31,
city: "New York"
}
you can parse this string like this
try {
JSONObject obj=new JSONObject(response);
String name=obj.getString("name");
int age=obj.getInt("age");
String city=obj.getString("city");
} catch (JSONException e) {
e.printStackTrace();
}

You can use Gson for that:
First put the dependency in your app level build.gradle file.
implementation 'com.google.code.gson:gson:2.8.6'
Then you can add this:
var gson = new Gson()
var st = gson.toJson(response)
Log.i("GoogleIO","Response is : $st")

Related

Problem when sending jsonArray using socket.io Android

When I send my JSONArray object through socket like this:
val json = JSONArray()
....
socket?.emit(EVENT, json)
server gets my message as array within array, like:
[ [ { lat: 31.476369999999996, long: 74.26562} ], 'Function0<kotlin.Unit>' ]
I want to send only this:
[ { lat: 31.476369999999996, long: 74.26562} ]
Example code to send json array using custom arraylist
var obj: JSONObject? = null
val jsonArrayLatLng = JSONArray()
for (i in 0 until list!!.size) {
obj = JSONObject()
try {
obj.put("lat", list.get(i).lat)
obj.put("long", list.get(i).lng)
} catch (e: JSONException) {
e.printStackTrace()
}
jsonArrayLatLng.put(obj)
}
val jsonObject = JSONObject()
jsonObject.put("list_key_name_here", jsonArrayLatLng)
socket?.emit(EVENT, jsonObject)
This worked
socket?.emit(EVENT, jsonArray.toTypedArray())

How to call JSONObject in Retrofit api calls?

Example: My input is
"items":[{
"service_id":"1",
"service_description":"description here",
"service_quantity":1,
"service_uom":"number",
"service_price":"10000",
"service_total":"10000",
"service_taxid":1,
"service_taxvalue":"10"
},
{
"service_id":"2",
"service_description":"description here",
"service_quantity":1,
"service_uom":"number",
"service_price":"10000",
"service_total":"10000",
"service_taxid":1,
"service_taxvalue":"10"
}]
I declared like: API Call-
#FormUrlEncoded
#POST("URL")
Observable<SampleResponse> generateInvoice(#Field("items") JSONArray params);
Declaration:
JSONObject service1 = new JSONObject();
try {
service1.put("service_id", id);
service1.put("service_description", Desc);
service1.put("service_quantity", Integer.valueOf(Qty));
service1.put("service_uom", "number");
service1.put("service_price", Amt);
service1.put("service_total", GAmt);
service1.put("service_taxid", 1);
service1.put("service_taxvalue", 5);
Log.d("jsonobject created",""+service1);
}
catch (JSONException e) {
e.printStackTrace();
}
JSONArray array = new JSONArray().put(service1);
presenter.generateInvoice(array);
Error at backend: '{\"service_id\":3,\"service_description\":\"Mobile
Application\",\"service_quantity\":5,\"service_uom\":\"number\",\"service_price\":\"650\",\"service_total\":\"3640\",\"service_taxid\":1,\"service_taxvalue\":5}';
You need to make 2 pojo class based on your request.
class RequestClass {
#SerializedName("items")
#Expose
var items: List<Item> = arrayListOf()
}
Item class will contains all the string fields that you have in your request, and in retrofit api you need to pass RequestClass like below. and remove the #FormUrlEncoded
#POST("URL")
Observable<SampleResponse> generateInvoice(#Body RequestClass requestClass);

Volley error response bytes does not convert from bytes to string

CustomStringRequest customStringRequest = new CustomStringRequest(requestMethod.ordinal(), serverUrl,
result -> {
Log.d(TAG, "headers: " + result.headers);
Log.d(TAG, "response: " + result.response);
createTaskItem(result);
},
error -> {
Log.d(TAG, "error: " + error);
})
error is in JSON string, I tried to get error like this:
new String(error.networkResponse.data, "utf-8");
new String(error.networkResponse.data);
none of the above method works, i always get empty string, don't know why :(
as you can see bytes in picture, the error response is actually this:
{
"error": [
"Wrong Credentials!"
],
"email_exists": false
}
I am using:
implementation 'com.android.volley:volley:1.1.1'
You can convert your response to json object using GSON ,
val customPojo = CustomPojo()
val gson = Gson()
gson.toJson(myPojo)
CustomPojo should be your response model class.
oh, i was just evaluating error response in debug mode
new String(error.networkResponse.data, "UTF-8");
and it returns empty string in result.
I just tried to print error response and it worked!. Thanks.

How to parse Json data in android for Firebase Cloud Messaging (FCM)

i am using FCM for push messages and handling all incoming push notification in onMessageReceived. Now the issue is with parsing nested json that comes inside this function remoteMessage.getData()
I have following block coming as a push notification in device. content of data payload could be varied here it is dealer later on it can be productInfo
{
"to": "/topics/DATA",
"priority": "high",
"data": {
"type": 6,
"dealerInfo": {
"dealerId": "358",
"operationCode": 2
}
}
}
this how i am parsing it
if(remoteMessage.getData()!=null){
JSONObject object = null;
try {
object = new JSONObject(remoteMessage.getData());
} catch (JSONException e) {
e.printStackTrace();
}
}
now i am getting data with blackslashes as remoteMessage.getData() returns Map<String,String> so probably my nested block is being converted in string not sure though.
{
"wasTapped": false,
"dealerInfo": "{\"dealerId\":\"358\",\"operationCode\":2}",
"type": "6"
}
and if i write object = new JSONObject(remoteMessage.getData().toString()); then it got failed with following notification
{
"to": "regid",
"priority": "high",
"notification" : {
"body": "Message Body",
"title" : "Call Status",
"click_action":"FCM_PLUGIN_ACTIVITY"
},
"data": {
"type": 1,
"callNumber":"ICI17012702",
"callTempId":"0",
"body": "Message Body",
"title" : "Call Status"
}
}
error i get is
> org.json.JSONException: Unterminated object at character 15 of
> {body=Message Body, type=1, title=Call Status, callNumber=ICI17012702,
> callTempId=0}
try this code:
public void onMessageReceived(RemoteMessage remoteMessage)
{
Log.e("DATA",remoteMessage.getData().toString());
try
{
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
Log.e("JSON OBJECT", object.toString());
String callNumber = object.getString("callNumber");
//rest of the code
}
}
Also make sure your JSON is valid use This
Faced this issue when migrating from GCM to FCM.
The following is working for my use case (and OP payload), so perhaps it will work for others.
JsonObject jsonObject = new JsonObject(); // com.google.gson.JsonObject
JsonParser jsonParser = new JsonParser(); // com.google.gson.JsonParser
Map<String, String> map = remoteMessage.getData();
String val;
for (String key : map.keySet()) {
val = map.get(key);
try {
jsonObject.add(key, jsonParser.parse(val));
} catch (Exception e) {
jsonObject.addProperty(key, val);
}
}
// Now you can traverse jsonObject, or use to populate a custom object:
// MyObj o = new Gson().fromJson(jsonObject, MyObj.class)
I have changed to
JSONObject json = new JSONObject(remoteMessage.getData());
from
JSONObject json = new JSONObject(remoteMessage.getData().toString());
and work fine.
Since dealerInfo is parsed as string and not an object, create a new JSONObject with the string
JSONObject dealerInfo = new JSONObject(object.getString("dealerInfo"));
String dealerId = dealerInfo.getString("dealerId");
String operationCode = dealerInfo.getString("operationCode");
I didn't want to add GSON (as I use moshi) to make it working, so I made Kotlin method to form json string from remoteMessage's map, tested this on one example, so don't forget to test this implementation before using:
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
var jsonString = "{"
remoteMessage?.data?.let {
val iterator = it.iterator()
while (iterator.hasNext()) {
val mapEntry = iterator.next()
jsonString += "\"${mapEntry.key}\": "
val value = mapEntry.value.replace("\\", "")
if (isValueWithoutQuotes(value)) {
jsonString += value
} else {
jsonString += "\"$value\""
}
if (iterator.hasNext()) {
jsonString += ", "
}
}
}
jsonString += "}"
println(jsonString)
}
private fun isValueWithoutQuotes(value: String):Boolean{
return (value == "true" || value == "false" || value.startsWith("[") || value.startsWith("{") || value == "null" || value.toIntOrNull() != null )
}
Edit:
Even better approach is to form FCM data like:
notificationType: "here is ur notification type"
notificationData: {
//here goes ur data
}
That way we can retreive both values from map.
remoteMessage?.data?.let {
it["notificationData"]?.let {
jsonString = it.replace("\\", "")
}
}
We got clear json without "playing" around.
And we can then use notificationType to convert json to the object that we need (as several notification data types can be passed sometimes)
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
// if (/* Check if data needs to be processed by long running job */ true) {
// // For long-running tasks (10 seconds or more) use WorkManager.
// scheduleJob();
// } else {
// // Handle message within 10 seconds
// handleNow();
// }
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}

How to send Array of Objects in retrofit Android?

I have an below array of objects to be passed in the service call.
[
{
"ParkingSpace": {
"sid": "WorldSensing.vhu6lom3sovk6ahpogebfewk5kqadvs4.5385fc250cf2497dfe5679d1"
}
},
{
"ParkingSpace": {
"sid": "WorldSensing.vhu6lom3sovk6ahpogebfewk5kqadvs4.5385ff2f0cf2497dfe567c0c"
}
},
{
"ParkingSpace": {
"sid": "WorldSensing.vhu6lom3sovk6ahpogebfewk5kqadvs4.5385fd700cf2e65ecf6330c6"
}
}, {
"ParkingSpace": {
"sid": "WorldSensing.vhu6lom3sovk6ahpogebfewk5kqadvs4.5385fefe0cf2497dfe567bee"
}
}, {
"ParkingSpace": {
"sid": "WorldSensing.vhu6lom3sovk6ahpogebfewk5kqadvs4.5385ff690cf2497dfe567c3f"
}
}, {
"ParkingSpace": {
"sid": "WorldSensing.vhu6lom3sovk6ahpogebfewk5kqadvs4.55e972d21170d0c2fd7d15b1"
}
}]
I am trying like below:
private String generateParkingspaceBody(final List<String> listOfsIds) {
//sids array
JSONArray sidsArray = new JSONArray();
for (String sId: listOfsIds) {
//creating sidObject and object
JSONObject sIdObject = new JSONObject();
JSONObject object = new JSONObject();
try {
sIdObject.put("sid", sId);
object.put("ParkingSpace",sIdObject);
sidsArray.put(object);
} catch (JSONException e) {
CPALog.e(TAG,e.getMessage());
}
}
return sidsArray.toString();
}
Sending this string into the service call like:
Response getNearByParkingSpaces(#Header("Authorization") String accessToken,
#Header("Content-Type") String contentType,
#Body String arrayOfSids);
But in request showing in the logact is :
"[{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}},{\"ParkingSpace\":{}}]"
Please help me, how to send this request?
Thanks in advance.
You don't need to convert your object to a JSONArray, Retrofit will do it automatically for you.
Simply change your API method declaration to:
#Headers({
"Content-type: application/json"
})
Response getNearByParkingSpaces(#Header("Authorization") String accessToken,
#Body List<String> arrayOfSids);
I encounter same issue solve this by adding this dependencies:
implementation 'com.squareup.retrofit2:converter-scalars:$version'
There are multiple existing Retrofit converters for various data formats. You can serialize and deserialize Java objects to JSON or XML or any other data format and vice versa. Within the available converters, you’ll also find a Retrofit Scalars Converter that does the job of parsing any Java primitive to be put within the request body. Conversion applies to both directions: requests and responses.
https://futurestud.io/tutorials/retrofit-2-how-to-send-plain-text-request-body
then you can use your generateParkingspaceBody as value to post.
generateParkingspaceBody.toString() as your request body

Categories

Resources