OkHttp发布正文为JSON


75

所以,当我使用Koush的离子时,我能够使用一个简单的方法将json正文添加到我的帖子中 .setJsonObjectBody(json).asJsonObject()

我要转到OkHttp,但我确实没有找到一种很好的方法。我到处都是错误400。

谁有想法?

我什至尝试手动将其格式化为json字符串。

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

编辑:对于以后在这个问题上遇到麻烦的人,这是我的解决方案,它异步执行所有操作。所选答案正确,但是我的代码有些不同。

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

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

String jsonString = json.toString();
RequestBody body = RequestBody.create(JSON, jsonString);

Request request = new Request.Builder()
    .header("X-Client-Type", "Android")
    .url(url)
    .post(body)
    .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();
        }
    });*/

...

private void runOnUiThread(Runnable task) {
    new Handler(Looper.getMainLooper()).post(task);
}

还有更多工作,主要是因为您必须回到UI线程才能执行任何UI工作,但是HTTPS的好处是……可以工作。


您的网址开头是否包含“ http://”?
Android Android

https://开头,实际上,却是
像素完美的

您是否信任应用程序的证书?
Android Android

好吧,看到我得到{“原因”:“不适当”}响应{协议= http / 1.1,代码= 200,消息=确定,URL = api / id /报告} {“原因”:“版权”}响应{ protocol = http / 1.1,code = 400,message = Bad Request,url = api / id / report } 23分钟
Pixel Perfect

它拿出我的https://作为url =
Pixel Perfect

Answers:


137

只需使用JSONObject.toString(); 方法。看看OkHttp的教程:

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

好吧,我需要查看后端是否正常运行。您的代码与我的代码的行为相同-当我为JSON中的字符串提供一件事时崩溃,但是当我提供不同的东西时却崩溃了。
Pixel Perfect

原来,我的问题只是我的JSON数据本身是错误的。我提供的字符串不正确。“ Copyright” .equals(“ CopyrightInfringement”)返回false
Pixel Perfect,

3
RequestBody.create()已弃用
Iman Marashi

2
@Iman Marashi不赞成使用的方法名称。不推荐使用方法参数。实际上,最新版本仅将MediaType替换为第二个参数。什么都没有改变。所以,应该是RequestBody body = RequestBody.create(json, JSON);And .....问题已解决
poring91 '20

1
@HardikParmar,这不是被弃用的方法名,而是一个参数。正如poring91所述,只需替换第一和第二个论点即可
Ostap Andrusiv '20

13

你可以创建自己的JSONObject,然后toString()

记得像doInBackground在中那样在后台线程中运行它AsyncTask

OkHttp版本> 4:

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

11

另一种方法是使用FormBody.Builder()
这是回调的示例:

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

然后,我们创建自己的主体:

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

最后,我们调用服务器:

client.newCall(request).enqueue(loginCallback);

谢谢,这个答案非常适合我。但是我有一个问题,什么是发送带有JSON类型的额外参数的最佳方法?这就是请求如何工作的图像,这就是我发送RequestBody信息图像的方式。该代码运行良好,但是我从响应中收到一条错误消息,告诉我Image参数不正确。也许我需要变成一个对象并解析为String?。在此先感谢您
马丁·塞拉诺

1
如何将JSON作为块添加到FormBody中,而不必手动添加每个键值对。
user3561494 '20

1

在okhttp v4中。*我以这种方式工作


// 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


奇迹般有效!Thnx
Mikhail Vasilev

1
不工作 这个不成立。json是一个String。一个String没有toRequestBody()方法
parsecer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.