Android - Weird EscapeUtil.unescapeString crash - java

I am getting a crash on receiving a JSON string from our applications server. We believe that when an entry has "quotes", there are extra escapes added.
In android, how can I determine if I receive such a string , and how do I fix it from the Android side?
Here is our current response string processing:
public String processResponseString(String responseString) {
if (responseString.startsWith("\"")) {
responseString = responseString.substring(1, responseString.length());
}
if (responseString.endsWith("\"")) {
responseString = responseString.substring(0, responseString.length() - 1);
}
responseString = EscapeUtil.unescapeString(responseString);
return responseString;
}
Also, logcat does not include the entire json string after the crash, so I cannot see the actual string that is causing the crash.
Exception
java.lang.ClassCastException: com.optiisolutions.housekeeping.model.OptiiAPI.OptiiError cannot be cast to java.util.Map
at com.optiisolutions.housekeeping.network.OptiiHTTPClientRetroFit$2.success(OptiiHTTPClientRetroFit.java:186)
at retrofit.CallbackRunnable$1.run(CallbackRunnable.java:45)
OptiiHTTPClientRetroFit.java:186
optiiClient.postRequest(event.getRequest(), new Callback<Map<String, Object>>() {
#Override
public void success(Map<String, Object> stringObjectMap, Response response) {
Log.d(TAG, "Successful response: " + stringObjectMap.toString());
String result = (String) stringObjectMap.get(OPTII_RESULT_TYPE);
String json = gson.toJson(stringObjectMap, Map.class);

I think you need to parse Map in to JSON Like below code by using JSONValue.
optiiClient.postRequest(event.getRequest(), new Callback<Map<String, Object>>() {
#Override
public void success(Map<String, Object> stringObjectMap, Response response) {
Log.d(TAG, "Successful response: " + stringObjectMap.toString());
// For JsonValue you need to add one jar file .
String json= JSONValue.toJSONString(stringObjectMap);
Log.d(TAG, "Successful json: " + json);
}
need to add jar javax.json-1.0.2.jar in gradle dependencies
dependencies {
compile files('libs/javax.json-1.0.2.jar')
}
Download javax.json-1.0.2.jar Download from below link:
http://www.java2s.com/Code/Jar/j/Downloadjavaxjson102jar.htm

I tried to replicate your string. I'm assuming you want to keep the quotes. I could solve it with this simple algorithm, hope it works for you:
public static String process(String s){
String sep = "\\\\";
String[] arr = s.split(sep);
StringBuilder sb = new StringBuilder();
for(String str : arr){
sb.append(str);
}
return sb.toString();
}

Related

Error 400, Bad Request, Json Parse error: Unrecognized token 'agama' : was Expecting ('true','false', or 'null') in Android Retrofit with Spring Boot

I have this kind of JSON:
EDITED
{
"tgl_Lahir": "1960-12-18 00:00:00",
"nama": "Rahmi P",
"keterangan": "HIDUP",
"tempatLahir": "YOGYAKARTA",
"noPegawai": "010713",
"golDarah": "0",
"statusNikah": "0",
"hubungans": {
"id": "10"
},
"agama": {
"id_Agama": "1"
},
"jeniskelamin": {
"jenisKelamin": "1"
}
}
I have this interface class:
#FormUrlEncoded
#POST("http://ipaddress/family/add")
Call<familylistresponse> addFams(#Header("Content-Type") String content_type,
#Header("Authorization") String auth,
#Query("id") String id,
// #Field("noPegawai") JSONObject noPegawai,
#Field("agama") JSONObject agama,
#Field("hubungans") JSONObject hubungans,
#Field("jeniskelamin") JSONObject jeniskelamin,
#Field("tgl_Lahir") JSONObject tgl_lahir,
#Field("nama") JSONObject nama,
#Field("keterangan") JSONObject keterangan,
#Field("tempatLahir") JSONObject tempatLahir,
#Field("golDarah") JSONObject goldar,
#Field("statusNikah") JSONObject statusNikah);
I want to store my data to database server so I add this method inside my button.setOnClickListener:
public void addFamily(String noPegawai, String agama, String hubungan, String jenisKelamins, String tgl_Lahir, String nama, String keterangan, String tempatLahir, String golDarah, String statusNikah){
String id=null;
SharedPreferences preferences = getSharedPreferences("MyPref",0);
String tokens = preferences.getString("userToken",null);
try {
jsonObject.put("noPegawai", noPegawai);
jsonObject.put("agama", agama);
jsonObject.put("hubungans", hubungan);
jsonObject.put("jeniskelamin", jenisKelamins);
jsonObject.put("tgl_Lahir", tgl_Lahir);
jsonObject.put("nama", nama);
jsonObject.put("keterangan", keterangan);
jsonObject.put("tempatLahir", tempatLahir);
jsonObject.put("golDarah", golDarah);
jsonObject.put("statusNikah", statusNikah);
} catch (JSONException e) {
e.printStackTrace();
}
Call<familylistresponse> call = apiService.addFams("application/json","Bearer " + tokens , id, jsonObject, jsonObject, jsonObject, jsonObject , jsonObject, jsonObject, jsonObject, jsonObject, jsonObject);
call.enqueue(new Callback<familylistresponse>() {
#Override
public void onResponse(Call<familylistresponse> call, Response<familylistresponse> response) {
try {
if(response.body()!=null)
Toast.makeText(TambahDataKeluarga.this," response message success "+response.body(),Toast.LENGTH_LONG).show();
if(response.errorBody()!=null)
Toast.makeText(TambahDataKeluarga.this," response message error "+response.errorBody().string(),Toast.LENGTH_LONG).show();
Log.e("ERROR: ", response.errorBody().string());
}catch (Exception e){
e.printStackTrace();
}
Toast.makeText(TambahDataKeluarga.this," Tokens "+tokens,Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<familylistresponse> call, Throwable t) {
Log.e("ERROR: ", t.getMessage());
}
});
}
but when I try to post it to the server it shows me this error
Any ideas? or it's because of my nested son? or my interface's class? Thank you
"agama":
{
"id_Agama": "1"
}
but agama is just a string so solve it like this
"agama":"1"
set your value like this.
JSONObject jobj = new JSONObject();
try {
jobj.put("id_Agama", "1");
} catch (JSONException e) {
e.printStackTrace();
}
pass in your request like this.
#Field("agama") JSONObject jobj,
interface class:
#FormUrlEncoded
#POST("http://103.82.240.144:1111/WSHRIS/pegawai/family/add")
Call<familylistresponse> addFams(#Header("Content-Type") String content_type,
#Header("Authorization") String auth,
#Query("id") String id,
#Field("noPegawai") boolean noPegawai,
#Field("agama") JSONObject agama,
#Field("hubungans") JSONObject hubungans,
#Field("jeniskelamin") JSONObject jeniskelamin,
#Field("tgl_Lahir") String tgl_lahir,
#Field("nama") String nama,
#Field("keterangan") String keterangan,
#Field("tempatLahir") String tempatLahir,
#Field("golDarah") String goldar,
#Field("statusNikah") String statusNikah);
Pass in argument JSON object in argument
public void addFamily(String noPegawai, String agama, String hubungan, String jenisKelamins, String tgl_Lahir, String nama, String keterangan, String tempatLahir, String golDarah, String statusNikah){
String id=null;
SharedPreferences preferences = getSharedPreferences("MyPref",0);
String tokens = preferences.getString("userToken",null);
JSONObject agamajsonObject= new JSONObject();
JSONObject hubungansjsonObject= new JSONObject();
JSONObject jeniskelaminjsonObject= new JSONObject();
try {
agamajsonObject.put("id_Agama", "1");
hubungansjsonObject.put("id", "10");
jeniskelaminjsonObject.put("jenisKelamin", "1");
} catch (JSONException e) {
e.printStackTrace();
}
Call<familylistresponse> call = apiService.addFams("application/json","Bearer " + tokens , id, true, agamajsonObject, hubungansjsonObject, jeniskelaminjsonObject, tgl_Lahir, nama, keterangan, tempatLahir, golDarah,statusNikah);
call.enqueue(new Callback<familylistresponse>() {
#Override
public void onResponse(Call<familylistresponse> call, Response<familylistresponse> response) {
try {
if(response.body()!=null)
Toast.makeText(TambahDataKeluarga.this," response message success "+response.body(),Toast.LENGTH_LONG).show();
if(response.errorBody()!=null)
Toast.makeText(TambahDataKeluarga.this," response message error "+response.errorBody().string(),Toast.LENGTH_LONG).show();
Log.e("ERROR: ", response.errorBody().string());
}catch (Exception e){
e.printStackTrace();
}
Toast.makeText(TambahDataKeluarga.this," Tokens "+tokens,Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<familylistresponse> call, Throwable t) {
Log.e("ERROR: ", t.getMessage());
}
});
}
I've SOLVED THE ISSUE!
I don't know if this will become a solution for future readers or not. But at least it'll help a little bit.
1. Interface Class: I just change the form format into #Body type, I think it makes me easier to actually insert the data, you just have to sort your input type value in sequence so that it will automatically be inserted to your server API input format.
#Headers({ "Content-Type: application/json;charset=UTF-8"})
#POST("http://ipaddress/family/add/")
Call<familylistresponse> addFams(#Header("Authorization") String auth,
#Body familylistresponse familybody);
2. Nested Objects: So before, I've tried some solutions that you guys gave to me these days, and thank you for that. But what I did to solve my issue was different. So as you can see that I have nested objects on agamas, hubungans, and jeniskelamin. What did I do? It's just a simple one, like this (Call your "GSON Generate Class") like this :
Agama agamas = new Agama();
agamas.setIdAgama(vAgama);
Jeniskelamin jks = new Jeniskelamin();
jks.setJenisKelamin(vJenisk);
Hubungans hubungans = new Hubungans();
hubungans.setId(vHub);
After that, you just need to add those variables into your Main Model Class in your Activity :
familylistresponse f = new familylistresponse();
f.setTglLahir(name);
f.setAgama(agamas);
f.setHubungan(hubungans);
etc....
And BOOM! There you go~
This is an additional TIPS: Make sure your variables on the client's app are the same as you've settled on your database server! :D Ur Welcome ~~
Please vote for this answer if you feel that it is helpful!

java.lang.IllegalArgumentException: Object would be serialized to `null`: Android

I have recently been setting up mobile apps to work with my meteor server. As a part of this I have to pass the meteor web app data from android. Unfortunately I have been receiving a error that tells me that the java object I am passing "would be serialized to null". How do I prevent this?
JSONObject json = new JSONObject();
try{
json.put("Foo", "1");
json.put("Blah", 0);
}catch (JSONException e){
}
Object[] object = new Object[1];
object[0] = json;
System.out.println(object + ", " + object[0] + ", " + object[0].toString());
mMeteor.call("xxx", object, new ResultListener() {
#Override
public void onSuccess(String result) {
}
#Override
public void onError(String error, String reason, String details) {
}
});
}
#Override
public void onError(String error, String reason, String details) {
}
});
Android/Meteor interface Library function
public void callWithSeed(final String methodName, final String randomSeed, final Object[] params, final ResultListener listener) {
// create a new unique ID for this request
final String callId = uniqueID();
// save a reference to the listener to be executed later
if (listener != null) {
mListeners.put(callId, listener);
}
// send the request
final Map<String, Object> data = new HashMap<String, Object>();
data.put(Protocol.Field.MESSAGE, Protocol.Message.METHOD);
data.put(Protocol.Field.METHOD, methodName);
data.put(Protocol.Field.ID, callId);
if (params != null) {
data.put(Protocol.Field.PARAMS, params);
}
if (randomSeed != null) {
data.put(Protocol.Field.RANDOM_SEED, randomSeed);
}
send(data);
}
I was having this same issue, my first error was passing a CharSequence instead a String as a parameter (your Object[]), and my other error was passing an Object[] as another parameter (I solved this by sending a String instead, like : String.valueOf(your_object_list)) Dont forget to handle this on your server side, you will receive a String instead of an Object.
Convert the JSONArray to List & JSONObject to HashMap and then pass those instead of the raw JSONObject or JSONArray.
You can write a recursive function for the conversion in case of nested JSONObject and JSONArray or can use GSON library for the conversion.
For more details about the conversion, this SO post may be helpful.

Volley String cannot be converted to JSONObject

I'm always getting the following error as long as i put a array into Params. Even after converting to String it still gives that error. The code works fine without the contactlist array inside it. Any idea?
Error
com.android.volley.ParseError: org.json.JSONException: Value Created
of type java.lang.String cannot be converted to JSONObject
Sample response:
{
"username": "test2",
"lists": [
"contact_0",
"contact_1",
"contact_2",
"contact_3",
"contact_4",
"contact_5",
"contact_6",
"contact_7",
"contact_8",
"contact_9"
]
}
ArrayList<String> contactList = new ArrayList<String>();
public String joinInfo;
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println("name : " + name + ", ID : " + phoneNumber);
joinInfo = name;
contactList.add(joinInfo);
}
phones.close();
RequestQueue rq = Volley.newRequestQueue(this);
JSONObject params = new JSONObject();
try {
params.put("username", "test2");
params.put("lists", contactList.toString()); // When i change this to simply "test" a string, it works fine.
Log.d("PANDA", contactList.toString());
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
"http://postcatcher.in/catchers/55521f03f708be0300001d28", params, //Not null.
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("PANDA", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("PANDA", "Error: " + error.getMessage());
Log.d("PANDA", error.toString());
}
});
// Adding request to request queue
rq.add(jsonObjReq);
PostCatcher although allowing us to post requests, its response is basically a plain string "Created" and not in Json format. As such our client code is not able to ascertain it and throws error. One thing is even without ArrayList object that is with plain (String, String) K,V pair also it would fail.
You can verify it if you try sending request through Advanced Rest Client (see attached)

java.lang.NullPointerException when POST with AsyncHttpClient

I have an endpoint /test which expects Map :
#POST("/hello")
#PermitAll
public JSONObject test(Map param) throws JsonParseException {
String elementName = param.get("name").toString();
String elem = param.get("elem").toString();
JSONObject json=new JSONObject();
try {
json.put("id",1);
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
And I'm sending asynchronous POST (postin JSON) using AsyncHttpClient:
public static void asyncCallPost(JSONObject jsonData) throws Exception {
AsyncHttpClient client = new AsyncHttpClient();
try {
Response response = client.preparePost(url)
.addHeader("Content-Type", "application/json")
.addHeader("Content-Length", "" + jsonData.length())
.setBody(jsonData.toString()).execute().get();
if (response.getStatusCode() != 200) {
throw new Exception("Error ");
}
} finally {
client.close();
}
}
But I am getting java.lang.NullPointerException.
Is it because I don't pass any Map to /hello? If so how make POST with jsonData as Map to the endpoint?
I cannot tell without further information however I suspect that the following needs to change;
String elementName = param.get("name").toString();
String elem = param.get("elem").toString();
to
String elementName;
if(param.get("name") != null){
elementName = param.get("name").toString();
}
String elem;
if(param.get("elem") != null){
elem = param.get("elem").toString();
}
The reason being the param.get("name") is returning a null which you are attempting to run toString on, hence the null pointer exception.
You're setting a JSON string to the body, that's why the Map is null or empty or full of garbage (I didn't check myself).
The Map is a representation of the key-value pairs that are POSTed. To have the Map non-empty, you would have to post e.g. name=myname&elem=myelement as type application/x-www-form-urlencoded.

Java sends a JSON string in POST request with escaped double quotes [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I stop HTTP from escaping quotes?
I am creating a JSONObject and sending JSON string to a server in a POST request body.
public String toJson() {
JSONObject filter = new JSONObject();
try {
filter.put("gender", gender.getCode());
filter.put("feature_id", productCategory);
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject filterObject = new JSONObject();
try {
filterObject.put("filter", filter);
} catch (JSONException e) {
e.printStackTrace();
}
return filterObject.toString();
}
So I'm creating a request:
private IJsonExecutorInterface requestExecutorForRelativePathAndParams(String path, WebParams params) throws UnsupportedEncodingException {
HttpPost postRequest = new HttpPost(rootUrl + path);
if(params != null) {
postRequest.setHeader("content-type", params.getContentType());
postRequest.setEntity(params.getFormEntity());
}
// Blah blah
return executor;
}
public IJsonExecutorInterface getProducts(ProductFilter filter, int offset, int limit) throws UnsupportedEncodingException {
WebParams webParams = new WebParams();
webParams.addPair("filter", filter.toJson());
webParams.addPair("offset", String.format("%d", offset));
webParams.addPair("limit", String.format("%d", limit));
return requestExecutorForRelativePathAndParams("products", webParams);
}
// WebParams class
public class WebParams {
private ArrayList<NameValuePair> params;
private String contentType = "application/x-www-form-urlencoded";
public WebParams() {
params = new ArrayList<NameValuePair>();
}
public void addPair(String name, String value) {
params.add(new BasicNameValuePair(name, value));
}
public String getContentType() {
return contentType;
}
public HttpEntity getFormEntity() throws UnsupportedEncodingException {
return new UrlEncodedFormEntity(params);
}
}
I see it in debugger: it's ok.
But on my server I getting something like this:
Array
(
[filter] => {\"gender\":\"w\",\"feature_id\":\"41_7459\"}
[offset] => 0
[limit] => 18
)
The quotes ARE escaped.
I don't want to replace something on the server. replace("\\\"", "\"") in Java doesn't affect on the string.
Looks like your using a UrlEncodedFormEntity, which, according to the docs is 'An entity composed of a list of url-encoded pairs' ([http://developer.android.com/reference/org/apache/http/client/entity/UrlEncodedFormEntity.html]). I've never used this, but it doesn't sound like its what you want, as you are sending data in the post body, not through URL parameters.
I've used the StringEntity class before to send json data via post, although it only encodes a string, not name/value pairs, so you've got to do a bit more work to put the string in a format you want to deal with on your server:
public class WebParams {
private ArrayList<NameValuePair> params;
private String contentType = "application/x-www-form-urlencoded";
public WebParams() {
params = new ArrayList<NameValuePair>();
}
public void addPair(String name, String value) {
params.add(new BasicNameValuePair(name, value));
}
public String getContentType() {
return contentType;
}
public HttpEntity getFormEntity() throws UnsupportedEncodingException {
//TODO: Build a string in what ever format you want.
// This will include the gender & feature_id fields as well as the json
StringBuilder b = new StringBuilder();
for(NameValuePair nvp : params) {
builder.append(nvp.getName()).append('=').append(nvp.getValue()).append(',');
}
//Now that we have a string to send to the server, get your entity!
StringEntity entity = new StringEntity(b.toString());
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
return entity;
}
}
Is there a problem to use simple quotes instead of double quotes? Because I think it would solve your problem.

Categories

Resources