OkHttp Post Body als JSON

73

Als ich Koushs Ion verwendete, konnte ich meinen Posts mit einem einfachen einen json-Körper hinzufügen .setJsonObjectBody(json).asJsonObject()

Ich gehe zu OkHttp und sehe wirklich keinen guten Weg, das zu tun. Ich bekomme überall Fehler 400.

Hat jemand irgendwelche Ideen?

Ich habe sogar versucht, es manuell als JSON-Zeichenfolge zu formatieren.

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

Bearbeiten: Für alle, die später auf diese Frage stoßen, ist hier meine Lösung, die alles asynchron macht. Die ausgewählte Antwort ist RICHTIG, aber mein Code ist etwas anders.

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

Ein bisschen mehr Arbeit, hauptsächlich, weil Sie zum UI-Thread zurückkehren müssen, um UI-Arbeiten auszuführen, aber Sie haben den Vorteil, dass HTTPS nur ... funktioniert.

Pixel Perfekt
quelle
Enthält Ihre URL beim Start "http: //"?
Android Android
https: //, eigentlich, aber ja
Pixel Perfect
Haben Sie Zertifikaten für Ihre App vertraut?
Android Android
Nun, da ich {"Grund": "Unangemessen"} Antwort bekomme {Protokoll = http / 1.1, Code = 200, Nachricht = OK, URL = API / ID / Bericht } {"Grund": "Copyright"} Antwort { Protokoll = http / 1.1, Code = 400, Nachricht = Bad Request, URL = API / ID / Bericht } 23 min
Pixel Perfect
es nahm meine https: // für die URL =
Pixel Perfect

Antworten:

135

Verwenden Sie einfach die JSONObject.toString(); Methode . Und schauen Sie sich das Tutorial von OkHttp an:

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();
}
Ostap Andrusiv
quelle
Nun, ich muss sehen, ob das Backend überhaupt richtig funktioniert. Ihr Code verhält sich identisch mit meinem - er stürzt ab, wenn ich eine Sache für die Zeichenfolge im JSON gebe, funktioniert aber, wenn ich etwas anderes gebe.
Pixel Perfect
Es stellte sich heraus, dass mein Problem nur darin bestand, dass meine JSON-Daten selbst falsch waren. Ich habe eine falsche Zeichenfolge angegeben. "Copyright" .equals ("CopyrightInfringement") gibt false zurück
Pixel Perfect
3
RequestBody.create () ist veraltet
Iman Marashi
2
@Iman Marashi Es ist nicht der Methodenname, der veraltet ist. Es ist das Methodenargument, das veraltet ist. Tatsächlich ersetzt die neueste Version nur den MediaType als zweites Argument. Mehr wird nicht geändert. Also sollte es sein RequestBody body = RequestBody.create(json, JSON);Und ..... Problem gelöst
poring91
1
@HardikParmar, es ist nicht der Methodenname, der veraltet ist, sondern ein Argument. Ersetzen Sie einfach das erste und das zweite Argument, wie von poring91 erwähnt
Ostap Andrusiv
13

Sie können Ihre eigene Gruppe gründen JSONObjectdann toString().

Denken Sie daran, es im Hintergrund-Thread wie doInBackgroundin auszuführen AsyncTask.

OkHttp Version> 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 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();
  }
Allen
quelle
11

Ein anderer Ansatz ist die Verwendung von FormBody.Builder().
Hier ist ein Beispiel für einen Rückruf:

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

Dann erschaffen wir unseren eigenen Körper:

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

Schließlich rufen wir den Server auf:

client.newCall(request).enqueue(loginCallback);
AbdulMomen عبدالمؤمن
quelle
Danke, diese Antwort funktioniert sehr gut für mich. Aber ich habe eine Frage, was der beste Ansatz wäre, um einen zusätzlichen Parameter mit JSON-Typ zu senden. Dies ist , wie die Anforderung arbeitet Bild , und das ist , wie ich das Senden von RequestBodyInformationen Bild . Der Code funktioniert gut, aber ich erhalte eine Fehlermeldung von der Antwort, dass der Parameter Image falsch war. Vielleicht muss ich mich in ein Objekt verwandeln und analysieren String? Vielen Dank im Voraus
Martín Serrano
1
Wie füge ich JSON zu einem FormBody als Block hinzu, ohne jedes Schlüsselwertpaar manuell hinzufügen zu müssen?
user3561494
1

In okhttp v4. * Ich habe es so zum Laufen gebracht


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

lcapra
quelle
Klappt wunderbar! Danke
Mikhail Vasilev
1
Funktioniert nicht. Das macht keinen Sinn. jsonist ein String. A Stringhat keine toRequestBody()Methode
Parsecer