¿Cómo puedo eliminar la clave nameValuePairs del JSONObject?
Estoy trabajando en un proyecto de Android que necesita un JSONObject para el cuerpo de mi solicitud POST. Después de poner las claves y valores del JSON me salió la siguiente línea:
{
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
Pero el servidor obtuvo lo siguiente:
{
"name_value_pairs": {
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
}
Ya probé un JSONStringer pero no fue realmente útil porque el nombre Content-Type
de la solicitud es application/json
.
ACTUALIZAR
No estoy intentando construir un JSONObject porque ya está hecho usando la siguiente línea de código (la misma proporcionada por @osayilgan):
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Aquí no está el problema. La interfaz que se describe a continuación se utiliza para comunicarse con el servidor.
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}
El servidor recibió la solicitud con el segundo JSON como Cuerpo, lo cual es decepcionante. Observo que la clave name_value_pairs
se agrega automáticamente al objeto.
¿Alguien sabe cómo puedo solucionar esto?
Asunto :
Retrofit utiliza de forma predeterminada GSON para convertir cuerpos HTTP hacia y desde JSON. El objeto especificado con la anotación @Body se pasará a GSON para su serialización, lo que básicamente convierte el objeto JAVA a una representación JSON. Esta representación JSON será el cuerpo de la solicitud HTTP.
JSONObject almacena toda la asignación clave-valor en una variable miembro por nombre nameValuePairs
. Aquí hay un extracto de la implementación de JSONObject:
public class JSONObject {
...
private final Map<String, Object> nameValuePairs;
...
}
Cuando pasa JSONObject a la anotación @Body, este JSONObject se serializa, por lo tanto, el cuerpo de la solicitud HTTP contiene: {"nameValuePairs": "actual JSON Object"}.
Solución:
Pase el objeto JAVA real a la anotación @Body, no su JSONObject correspondiente. GSON se encargará de convertirlo a representación JSON.
Por ejemplo
class HTTPRequestBody {
String key1 = "value1";
String key2 = "value2";
...
}
// GSON will serialize it as {"key1": "value1", "key2": "value2"},
// which will be become HTTP request body.
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void postJson(@Body HTTPRequestBody body, Callback<Response> callback);
}
// Usage
MyService myService = restAdapter.create(MyService.class);
myService.postJson(new HTTPRequestBody(), callback);
Solución alternativa:
Si aún desea enviar JSON sin formato como cuerpo de solicitud HTTP, siga la solución mencionada por el autor de Retrofit aquí .
Una de las soluciones sugeridas es utilizar TypedInput :
public interface MyService {
@POST("/test")
void postRawJson(@Body TypedInput body, Callback<Response> callback);
}
String json = jsonRequest.toString();
TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
myService.postRawJson(in, callback);
Utilice com.google.gson.JsonObject en lugar de org.json.JSONObject .
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Cambiar a
JsonObject jsonRequest = new JsonObject();
jsonRequest.addProperty("xxxx", "zzzzzzz");
jsonRequest.addProperty("yyyy", "uuuuuuu");
Luego en la interfaz
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void testFunction(@Body JsonObject jsonObject, Callback<Response> callback);
}
La clase JSONObject mantiene los valores LinkedHashMap
con el nombre de la variable nameValuePairs
. Cuando Gson intenta convertir la instancia de JSONObject en JSON, GSON mantiene la estructura (que tiene la variable nameValuePairs
). Eso está causando este problema.