Not a primitive array JsonException When i parse JsonArray - android

Here is the Response i am getting in this format
[{"id":15395,"firstName":"Real","lastName":"Me","phone":"(555) 455-6666","address1":"9800 Fredericksburg Road ","address2":null,"city":"San Antonio","state":"TX","zip":"78288"}]
If i parse the response as Json array i am getting JSONException.
Parsing the data as val jsonArray = JSONArray(response.body()!!)
but i am getting error as
Not a primitive array: class okhttp3.internal.http.RealResponseBody
Here is How i am calling api
val client = OkHttpClient().newBuilder()
.build()
val mediaType = MediaType.parse("application/json")
val body = RequestBody.create(mediaType, setPayloadSearch(value))
val request: Request = Request.Builder()
.url("https://api.etruckingsoft.com/ets/api/driver/searchDrivers")
.method("POST", body)
.addHeader(
"Authorization",
"----------------"
)
.addHeader("Content-Type", "application/json")
.build()
val response = client.newCall(request).execute()

response.body() returns a ResponseBody object. Due to this you are then calling the JSONArray(Object) constructor which expects the argument to be a Java array object, and therefore fails with a JSONException.
Instead (as mentioned in the comments) you should call response.body().string() to get the actual JSON content of the response and then call the JSONArray(String) constructor which parses the JSON data.

Related

Kotlin okhttp dynamic header

i am using okhttp (not retrofit) to make all my request to the api. It's working perfectly but i am having some trouble to make dynamique header. here is what i did :
private fun buildRequest(url: String, methode: Method = Method.GET, filters: Map<String, String> = mapOf(): Request? {
var builder = FormBody.Builder()
builder.add("body", "test")
val request = Request.Builder()
.url(url)
.addHeader("API-Key", apikey)
.post(formBody)
.build()
}
Problem is that i got a map filter that represent some header i need to add, but those are not hard coded but they are dynamique, it can be for exemple :
var filters = mapOf("limit" to "10", "sort" to "date")
But i can't do a static addHeader for the filters because i don't know if i am going to have some or not or which are they going to be.
My idea was to use newBuilder like this :
if (!filters.isNullOrEmpty()){
filters.forEach{
request.newBuilder()
request.addHeader(it.key, it.value)
.build()
}
Problem is that this doesn't add my new header to the call. I am I missing something on how to use newBuilder ? or is there a way to manage dynamique header with okhttp ?
You can use toHeaders() extension function of map to convert your map object to Headers.
All key-value pairs of the map can be easily added to headers like this
val request = Request.Builder()
.url(url)
.headers(filters.toHeaders())
Note - Using headers() would replace all previously added headers of
the request builder.
You can also add headers to request builder later, on using newBuilder()
request.newBuilder()
.headers(filters.toHeaders())

OKHttpClient Response - bad request

I get a response - Bad Request when making an api request using OKHttpClient. Can someone please help? Response Code - 400
https://sendgrid.com/docs/API_Reference/api_v3.html
val policy = StrictMode.ThreadPolicy.Builder()
.permitAll().build()
StrictMode.setThreadPolicy(policy)
val client = OkHttpClient()
val body: RequestBody = RequestBody.create(
"application/json".toMediaTypeOrNull(),
"{\"list_ids\":[\"a7aab3b0-\"],\"contacts\":[{\"email\": \"" + userEmail + "\"}]}"
)
val request: Request = Request.Builder()
.url("https://api.sendgrid.com/v3/marketing/contacts")
.put(body)
.addHeader("authorization", "Bearer SG.7LPq")
.addHeader("content-type", "application/json")
.build()
val response = client.newCall(request).execute()
It looks like your keys don't match the case being used in the API docs, they are capitalised. Also have you tried checking that toMediaTypeOrNull() is able to format that as JSON? It's difficult to tell how it will handle those slashes but they shouldn't be needed.

Retrofit returns unknown characters [duplicate]

This question already has an answer here:
Retrofit encoding special characters
(1 answer)
Closed 3 years ago.
I'm having this weird error when using Retrofit.
First of all I tried using okhttpClient just for comparison and im getting the json result as expected.
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("email", "my.email#email.com")
.build()
val request = Request.Builder()
.url(BASE_URL + "account/forgot")
.post(requestBody)
.build()
var client = OkHttpClient()
client.newCall(request).execute()
.use { response ->
val response = response.body()!!.string()
}
Which returns
{"success": true, "email": "my.email#email.com", "uu_id": "000-0--0-0-000"}
Now Using the same logic, I tried converting it to retrofit but skip the GSON conversion as it returns unexpected error saying "JSON is not formatted"
so what I did was on callback, just return it as ResponseBody based on Retrofit's Documentation
#Headers("token: ", "accept-language: en-US", "accept: application/json", "accept-encoding: gzip, deflate, br", "Content-Type: application/json")
#POST("account/forgot")
fun resetPasswordDetails(#Body body:String): Call<ResponseBody>
And uses this RetrofitInstance
public static Retrofit getRetrofitInstance() {
Gson gson = new GsonBuilder()
.setLenient()
.create();
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
.cookieJar(new JavaNetCookieJar(cookieManager))
.addInterceptor(loggingInterceptor)
.addInterceptor(new ResponseInterceptor())
.build();
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.client(defaultHttpClient)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
on my Main activity I used it as
val service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService::class.java)
val jsonBody = JSONObject()
jsonBody.put("email", "my.email#email.com")
val call = service.resetPasswordDetails(jsonBody.toString())
val response = call.execute()
val value = response.body()?.string()
I'm expecting the same result as what I did on okHttp but the return string was
���������������-�A
�0E�Rf)M1mc�+o"���)�ED�{��>��>PW"�.ݳ��w��Q����u�Ib�ȃd���x�/\r���#95s)�Eo���h�S����jbc���̚���� �������
Is there something wrong on my retrofit instance? Why is that it is working on okhttp but not on retrofit
EDIT:
My question is tagged as duplicate but I dont think thats the same question. While the other one states that the problem relates to URL encoding, My question is why is the okhttpclient and retrofit doesn't return the same JSON
Based on Xavier Rubio Jansana comment, I deleted some of my headers and now it is working properly. I just retain the #Headers("Content-Type: application/json").. Thanks a lot sir
It might be that you are sending the request as a JSON Body instead of Multipart like your OkHTTP request.
To make a Multipart request you can define your Retrofit request like this:
#POST("account/forgot")
fun resetPasswordDetails(#Part email:String): Call<ResponseBody>
Then you can just call the method with the email address without creating any JSONObject.

In Retrofit 422 code response I am not getting full error body response

I am not getting a full response string as JSON from retrofit 422 code
here is what I got in error body
[size=67 text=[{"field":"current_password","message":"Invalid current password…]
Thanks
Update
val listType = object : TypeToken<List<UpdatePasswordError>>() {}.type
val errorConverter: Converter<ResponseBody, List<UpdatePasswordError>> = networkClientI.mRetrofit.responseBodyConverter<List<UpdatePasswordError>>(listType, arrayOfNulls<Annotation>(0))
val errorList = errorConverter.convert(it.errorBody()!!)
I have successfully converted my response error body into Json
UpdatePasswordError.kt
data class UpdatePasswordError(
#SerializedName("field")
val `field`: String? = null,
#SerializedName("message")
val message: String? = null
)
Why did you decide that not all the string with an error comes in response? Did you check through Debagger? Try to handle the network error as described here: https://futurestud.io/tutorials/retrofit-2-simple-error-handling

Okhttp post json array

I am trying to do a post.
RequestBody formBody = new FormBody.Builder()
.add("userId", userId)
.add("patientName", patient.getName())
.add("patientDob", patient.getDOB())
.add("referralFor", patient.getFor())
.add("patientPhoto", "")
.add("message", "test")
.add("referralParticipants", )
.build();
however the referralParticipants is a json Array. Which also could be dynamic. I am unsure how to do this, as there is nothing in form data, it seems to just be raw json being sent??
This is how you are supposed to create RequestBody for media type application/json:
declare application/json media type:
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
Create request object:
RequestBody body = RequestBody.create(JSON, jsonStringToBePosted);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();

Categories

Resources