OkHttp Post Body as JSON

151,201

Solution 1

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();
}

Solution 2

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();
  }

Solution 3

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);

Solution 4

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

Share:
151,201

Related videos on Youtube

Pixel Perfect
Author by

Pixel Perfect

Updated on July 05, 2022

Comments

  • Pixel Perfect
    Pixel Perfect almost 2 years

    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();
                }
            });*/
    
    • Android Android
      Android Android over 8 years
      is your url contain "http://" at start?
    • Pixel Perfect
      Pixel Perfect over 8 years
      https://, actually, but yes
    • Android Android
      Android Android over 8 years
      Have you trusted certificates for your app?
    • Pixel Perfect
      Pixel Perfect over 8 years
      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 min
    • Pixel Perfect
      Pixel Perfect over 8 years
      it took out my https:// for the url=
    • Sabito 錆兎 stands with Ukraine
      Sabito 錆兎 stands with Ukraine over 3 years
      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.
  • Pixel Perfect
    Pixel Perfect over 8 years
    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.
  • Pixel Perfect
    Pixel Perfect over 8 years
    Turns out, my issue was just that my JSON data itself was wrong. I was supplying an incorrect string. "Copyright".equals("CopyrightInfringement") returns false
  • Martín Serrano
    Martín Serrano about 7 years
    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 advance
  • Clement Osei Tano
    Clement Osei Tano almost 5 years
    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.
  • Iman Marashi
    Iman Marashi over 4 years
    RequestBody.create() is Deprecated
  • poring91
    poring91 over 4 years
    @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 solved
  • Hardik Parmar
    Hardik Parmar over 4 years
    @Ostap Andrusiv Any other way ? Because this method is deprecated.
  • Ostap Andrusiv
    Ostap Andrusiv over 4 years
    @HardikParmar, it's not the method name that was deprecated, but an argument. Just replace the first and the second arguments, as poring91 mentioned
  • lcapra
    lcapra over 4 years
    In http4 is a bit different, see stackoverflow.com/a/60110536/833499
  • user3561494
    user3561494 almost 4 years
    How do you add JSON to a FormBody as a block without having to add each key value pair by hand.
  • parsecer
    parsecer almost 4 years
    Cannot resolve method create(String, MediaType) error
  • parsecer
    parsecer almost 4 years
    Not working. It makes no sense. json is a String. A String doesn't have toRequestBody() method
  • John Stone
    John Stone over 3 years
    Based on @parsecer 's comment, it is important to note that the above is not Java - it is Kotlin.
  • Firzen
    Firzen almost 3 years
    This is an outdated solution. Please see answer from @Allen.
  • LuGeNat
    LuGeNat over 2 years
    This does not work: val mediaType = "application/json; charset=utf-8".toMediaType();.
  • Kumararaja
    Kumararaja over 2 years
    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 this