OkHttp Post Body as JSON
Asked Answered
B

4

92

So, back when I was using Koush's Ion, I was able to add a json body to my posts with a simple .setJsonObjectBody(json).asJsonObject()

I'm moving over to OkHttp, and I really don't see a good way to do that. I'm getting error 400's all over the place.

Anyone have any ideas?

I've even tried manually formatting it as a json string.

String reason = menuItem.getTitle().toString();
JsonObject json = new JsonObject();
json.addProperty("Reason", reason);

String url = mBaseUrl + "/" + id + "/report";

Request request = new Request.Builder()
        .header("X-Client-Type", "Android")
        .url(url)
        .post(RequestBody
                .create(MediaType
                    .parse("application/json"),
                        "{\"Reason\": \"" + reason + "\"}"
                ))
        .build();

client.newCall(request).enqueue(new com.squareup.okhttp.Callback() {
    @Override
    public void onFailure(Request request, IOException throwable) {
        throwable.printStackTrace();
    }

    @Override
    public void onResponse(Response response) throws IOException {
        if (!response.isSuccessful()) throw new IOException(
                "Unexpected code " + response);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, "Report Received", Toast.LENGTH_SHORT).show();
            }
        });
    }
});

/*Ion.with(getContext(), url)
        .setHeader("X-Client-Type", "Android")
        .setJsonObjectBody(json)
        .asJsonObject()
        .setCallback(new FutureCallback<JsonObject>() {
            @Override
            public void onCompleted(Exception e, JsonObject result) {
                Toast.makeText(context, "Report Received", Toast.LENGTH_SHORT).show();
            }
        });*/
Blooming answered 9/12, 2015 at 13:22 Comment(6)
is your url contain "http://" at start?Forepeak
https://, actually, but yesBlooming
Have you trusted certificates for your app?Forepeak
Well, seeing as I get {"Reason":"Inappropriate"} Response{protocol=http/1.1, code=200, message=OK, url=api/id/report} {"Reason":"Copyright"} Response{protocol=http/1.1, code=400, message=Bad Request, url=api/id/report} 23 minBlooming
it took out my https:// for the url=Blooming
No answers in the question, please. I have rolled back/edited your question and removed the answer. Add the answer in the answer section only.Curcio
A
173

Just use JSONObject.toString(); method. And have a look at OkHttp's tutorial:

public static final MediaType JSON
    = MediaType.parse("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(json, JSON); // new
  // RequestBody body = RequestBody.create(JSON, json); // old
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  Response response = client.newCall(request).execute();
  return response.body().string();
}
Affidavit answered 9/12, 2015 at 13:32 Comment(10)
Well, I need to see if the backend is even working properly. Your code acts identically to mine - crashing when I supply one thing for the string in the JSON, but working when I supply something different.Blooming
Turns out, my issue was just that my JSON data itself was wrong. I was supplying an incorrect string. "Copyright".equals("CopyrightInfringement") returns falseBlooming
Do you have any way of going about it when the string is more than 32K characters without it being truncated? I've been facing this problem lately.Debor
RequestBody.create() is DeprecatedPomiculture
@Iman Marashi It's not the method name which is deprecated. It's the method argument which is deprecated. Actually, the latest version only replacing the MediaType as 2nd argument. Nothing more is changed. So, it should be RequestBody body = RequestBody.create(json, JSON); And..... problem solvedMaternity
@Ostap Andrusiv Any other way ? Because this method is deprecated.Lipfert
@HardikParmar, it's not the method name that was deprecated, but an argument. Just replace the first and the second arguments, as poring91 mentionedAffidavit
In http4 is a bit different, see https://mcmap.net/q/233782/-okhttp-post-body-as-jsonVintager
Cannot resolve method create(String, MediaType) errorBillman
This is an outdated solution. Please see answer from @Allen.Irtysh
B
32

You can create your own JSONObject then toString().

Remember run it in the background thread like doInBackground in AsyncTask.

OkHttp version > 4:

import okhttp3.MediaType.Companion.toMediaType

// create your json here
JSONObject jsonObject = new JSONObject();
try {
    jsonObject.put("KEY1", "VALUE1");
    jsonObject.put("KEY2", "VALUE2");
} catch (JSONException e) {
    e.printStackTrace();
}

val client = OkHttpClient()
val mediaType = "application/json; charset=utf-8".toMediaType()
val body = jsonObject.toString().toRequestBody(mediaType)
val request: Request = Request.Builder()
            .url("https://YOUR_URL/")
            .post(body)
            .build()

var response: Response? = null
try {
    response = client.newCall(request).execute()
    val resStr = response.body!!.string()
} catch (e: IOException) {
    e.printStackTrace()
}
   

OkHttp version 3:

// create your json here
JSONObject jsonObject = new JSONObject();
try {
    jsonObject.put("KEY1", "VALUE1");
    jsonObject.put("KEY2", "VALUE2");
} catch (JSONException e) {
    e.printStackTrace();
}

  OkHttpClient client = new OkHttpClient();
  MediaType JSON = MediaType.parse("application/json; charset=utf-8");
  // put your json here
  RequestBody body = RequestBody.create(JSON, jsonObject.toString());
  Request request = new Request.Builder()
                    .url("https://YOUR_URL/")
                    .post(body)
                    .build();

  Response response = null;
  try {
      response = client.newCall(request).execute();
      String resStr = response.body().string();
  } catch (IOException e) {
      e.printStackTrace();
  }
Balalaika answered 29/1, 2018 at 11:44 Comment(2)
This does not work: val mediaType = "application/json; charset=utf-8".toMediaType();.Rufena
if i try this ---> RequestBody body = RequestBody.create(JSON, jsonObject.toString()); added JSON Array inside JSON object, array value become string, want to pass only JSON Array data not string, anyone help me to solve thisThistly
F
11

Another approach is by using FormBody.Builder().
Here's an example of callback:

Callback loginCallback = new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        try {
            Log.i(TAG, "login failed: " + call.execute().code());
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // String loginResponseString = response.body().string();
        try {
            JSONObject responseObj = new JSONObject(response.body().string());
            Log.i(TAG, "responseObj: " + responseObj);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        // Log.i(TAG, "loginResponseString: " + loginResponseString);
    }
};

Then, we create our own body:

RequestBody formBody = new FormBody.Builder()
        .add("username", userName)
        .add("password", password)
        .add("customCredential", "")
        .add("isPersistent", "true")
        .add("setCookie", "true")
        .build();

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(this)
        .build();
Request request = new Request.Builder()
        .url(loginUrl)
        .post(formBody)
        .build();

Finally, we call the server:

client.newCall(request).enqueue(loginCallback);
Furtek answered 5/6, 2016 at 13:58 Comment(2)
Thanks, this answer work for me very well. But I have a question, what would be the best approach to sending an extra parameter with JSON type. This is how the request works image, and this is how I sending the RequestBody information image. The code works well but I receive an error from the response telling me that the Image parameter was incorrect. Maybe I need to turn into an object and parse to String?. Thanks in advanceMistress
How do you add JSON to a FormBody as a block without having to add each key value pair by hand.Crocodile
V
8

In kotlin, in okhttp v4.* I got it working that way


// import the extensions!
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody

// ...

json : String = "..."

val JSON : MediaType = "application/json; charset=utf-8".toMediaType()
val jsonBody: RequestBody = json.toRequestBody(JSON)

// go on with Request.Builder() etc

Vintager answered 7/2, 2020 at 9:25 Comment(2)
Not working. It makes no sense. json is a String. A String doesn't have toRequestBody() methodBillman
Based on @Billman 's comment, it is important to note that the above is not Java - it is Kotlin.Abyssinia

© 2022 - 2024 — McMap. All rights reserved.