Puede que esta pregunta se haya hecho antes, pero no, no se respondió definitivamente. ¿Cómo se publica exactamente un JSON completo sin procesar dentro del cuerpo de una solicitud de modificación?
Ver pregunta similar aquí . ¿O es correcta esta respuesta de que debe estar codificada en URL y pasar como un campo ? Realmente espero que no, ya que los servicios a los que me estoy conectando solo esperan JSON sin procesar en el cuerpo de la publicación. No están configurados para buscar un campo particular para los datos JSON.
Solo quiero aclarar esto con los expertos de una vez por todas. Una persona respondió que no debía usar Retrofit. El otro no estaba seguro de la sintaxis. Otro piensa que sí, se puede hacer, pero solo si su forma está codificada en URL y se coloca en un campo (eso no es aceptable en mi caso). No, no puedo volver a codificar todos los servicios para mi cliente Android. Y sí, es muy común en proyectos importantes publicar JSON sin formato en lugar de pasar contenido JSON como valores de propiedad de campo. Hagámoslo bien y sigamos adelante. ¿Alguien puede señalar la documentación o el ejemplo que muestra cómo se hace esto? O proporcione una razón válida por la que puede / no debe hacerse.
ACTUALIZACIÓN: Una cosa que puedo decir con 100% de certeza. PUEDES hacer esto en Google Volley. Está integrado directamente. ¿Podemos hacer esto en Retrofit?
RequestBody
así ->RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);
para respuestas detalladas futurestud.io/tutorials/…Respuestas:
La
@Body
anotación define un solo cuerpo de solicitud.Dado que Retrofit usa Gson de forma predeterminada, las
FooRequest
instancias se serializarán como JSON como el único cuerpo de la solicitud.Llamando con:
Producirá el siguiente cuerpo:
Los documentos de Gson tienen mucho más sobre cómo funciona la serialización de objetos.
Ahora, si realmente desea enviar JSON "en bruto" como el cuerpo usted mismo (¡pero use Gson para esto!) Todavía puede usar
TypedInput
:TypedInput se define como "Datos binarios con un tipo mime asociado". Hay dos formas de enviar fácilmente datos sin procesar con la declaración anterior:
Utilice TypedByteArray para enviar bytes sin formato y el tipo mime JSON:
Subclase TypedString para crear una
TypedJsonString
clase:Y luego use una instancia de esa clase similar al # 1.
fuente
TypedString
desde que se eliminó?RequestBody
para crear un cuerpo sin formato.java.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
En lugar de clases, también podemos usar directamente
HashMap<String, Object>
para enviar parámetros del cuerpo, por ejemplofuente
IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>
con Moshi. Creo que se necesita Gson para que esto funcioneSí, sé que es tarde, pero alguien probablemente se beneficiaría de esto.
Usando Retrofit2:
Anoche me encontré con este problema al migrar de Volley a Retrofit2 (y como OP dice, esto se incorporó directamente a Volley con
JsonObjectRequest
), y aunque la respuesta de Jake es la correcta para Retrofit1.9 , Retrofit2 no tieneTypedString
.Mi caso requería enviar un
Map<String,Object>
que pudiera contener algunos valores nulos, convertido a un JSONObject (que no volará con@FieldMap
, tampoco caracteres especiales, algunos se convierten), así que siguiendo la sugerencia de @bnorms, y como lo indica Square :Entonces esta es una opción usando
RequestBody
yResponseBody
:En su interfaz use
@Body
conRequestBody
En su punto de llamada, cree un
RequestBody
, indicando que es MediaType, y usando JSONObject para convertir su Mapa al formato adecuado:Espero que esto ayude a cualquiera!
Una elegante versión de Kotlin de lo anterior, para permitir abstraer los parámetros de la conversión JSON en el resto del código de su aplicación:
fuente
JsonObjectRequest
, todo lo que necesita hacer es esto. Buena respuesta.post a null value
acceder a una propiedad en requestBody que, de lo contrario, se ignoraba.jsonParams.put("code", some_code);
en la tercera línea?En Retrofit2 , cuando desee enviar sus parámetros en bruto, debe usar Scalars .
Primero agregue esto en su gradle:
Su interfaz
Actividad
fuente
GsonConverterFactory
,.toString()
no es necesario. Puede declararCall<User> getUser(@Body JsonObject body);
usando enJsonObject
lugar deJSONObject
y pasar elparamObject
directamente. Funcionará bien.Usar
JsonObject
es como es:Crea tu interfaz así:
Haga el JsonObject de acuerdo con la estructura jsons.
Llamar al servicio:
Y eso es! En mi opinión personal, es mucho mejor que hacer pojos y trabajar con el desorden de la clase. Esto es mucho más limpio.
fuente
Me gusta especialmente la sugerencia de Jake de la
TypedString
subclase anterior . De hecho, podría crear una variedad de subclases basadas en los tipos de datos POST que planea impulsar, cada uno con su propio conjunto personalizado de ajustes consistentes.También tiene la opción de agregar una anotación de encabezado a sus métodos JSON POST en su API Retrofit ...
... pero el uso de una subclase es más obviamente autodocumentado.
fuente
1) Agregar dependencias
2) haz la clase Api Handler
3) hacer clases de frijol a partir del esquema Json 2 pojo
http://www.jsonschema2pojo.org/
4) hacer interfaz para llamadas api
5) hacer JsonObject para pasar al cuerpo como parámetro
6) Llama a Api así
fuente
Descubrí que cuando usa un objeto compuesto como
@Body
params, no podría funcionar bien con el RetrofitGSONConverter
(bajo el supuesto de que está usando eso). Debe usarJsonObject
y noJSONObject
cuando trabaja con eso, agregaNameValueParams
sin ser detallado al respecto, solo puede ver eso si agrega otra dependencia de interceptor de registro y otras travesuras.Entonces, lo que encontré es el mejor enfoque para abordar esto
RequestBody
. Convierte su objetoRequestBody
con una simple llamada API y lo inicia. En mi caso estoy convirtiendo un mapa:y esta es la llamada:
fuente
Agregue ScalarsConverterFactory para actualizar:
en gradle:
su modificación:
cambie el parámetro @Body de su interfaz de llamada a String, no olvide agregar
@Headers("Content-Type: application/json")
:ahora puedes publicar json sin formato.
fuente
Puede usar hashmap si no desea crear una clase pojo para cada llamada a la API.
Y luego enviar así
fuente
usa siguiente para enviar json
y pásalo a url
fuente
Después de tanto esfuerzo, descubrió que la diferencia básica es que debe enviar el parámetro en
JsonObject
lugar de hacerloJSONObject
.fuente
Basado en la respuesta principal, tengo una solución para no tener que hacer POJO para cada solicitud.
Ejemplo, quiero publicar este JSON.
entonces, creo una clase común como esta:
Finalmente, cuando necesito un json
La solicitud marcada como anotación
@Body
puede pasar a Retrofit.fuente
Si no desea crear clases adicionales o usarlas
JSONObject
, puede usar aHashMap
.Interfaz de actualización:
Llamada:
fuente
Cosas necesarias para enviar json sin formato en Retrofit.
1) Asegúrese de agregar el siguiente encabezado y eliminar cualquier otro encabezado duplicado. Desde entonces, en la documentación oficial de Retrofit mencionan específicamente:
2) a. Si está utilizando una fábrica de convertidores, puede pasar su json como String, JSONObject, JsonObject e incluso POJO. También lo he comprobado, tenerlo
ScalarConverterFactory
no es necesario soloGsonConverterFactory
hace el trabajo.2) b. Si NO está utilizando ninguna fábrica de convertidores, DEBE utilizar RequestBody de okhttp3 como dice la documentación de Retrofit:
3) ¡Éxito!
fuente
Esto es lo que me funciona para la versión actual de
retrofit
2.6.2 ,En primer lugar, debemos agregar un convertidor de Scalars a la lista de nuestras dependencias de Gradle, que se encargaría de convertir los objetos java.lang.String en cuerpos de solicitud de texto / sin formato,
Luego, necesitamos pasar una fábrica de convertidores a nuestro generador de Retrofit. Más tarde le dirá a Retrofit cómo convertir el parámetro @Body pasado al servicio.
Luego, el servicio de actualización con un parámetro de cuerpo de cadena.
Luego crea el cuerpo JSON
Llama a tu servicio
fuente
✅✅✅✅✅✅✅✅✅✅✅✅ Solución de trabajo ✅✅✅✅✅✅✅✅✅✅✅✅
Durante la creación
OkHttpClient
, se usará para la actualización.agregue un interceptor como este.
Ahora el cuerpo URL y solicitar su reequipamiento de cada llamada se registra en
Logcat
. Filtrar por"gsonrequest"
fuente
Intenté esto: cuando esté creando su instancia de Retrofit, agregue esta fábrica de convertidores al generador de retrofit:
fuente
Resolvió mi problema basado en la respuesta de TommySM (ver anterior). Pero no necesitaba iniciar sesión, utilicé Retrofit2 para probar la API GraphQL https de esta manera:
Definí mi clase BaseResponse con la ayuda de anotaciones json (import jackson.annotation.JsonProperty).
Definió el procedimiento de llamada en la interfaz:
Llamado apicall en el cuerpo de la prueba: Cree una variable de tipo MyRequest (por ejemplo, "myLittleRequest").
fuente
Para mayor claridad sobre las respuestas dadas aquí, así es como puede usar las funciones de extensión. Esto es solo si está utilizando Kotlin
Si está utilizando
com.squareup.okhttp3:okhttp:4.0.1
los métodos más antiguos para crear objetos de MediaType y RequestBody han quedado en desuso y no se pueden usar en Kotlin .Si desea usar las funciones de extensión para obtener un objeto MediaType y un objeto ResponseBody de sus cadenas, primero agregue las siguientes líneas a la clase en la que espera usarlas.
Ahora puede obtener directamente un objeto de MediaType de esta manera
Para obtener un objeto de RequestBody, primero convierta el JSONObject que desea enviar a una cadena de esta manera. Tienes que pasarle el objeto mediaType.
fuente
Quería comparar la velocidad de la volea y la actualización para enviar y recibir datos que escribí debajo del código (para la parte de actualización)
primera dependencia:
Luego interfaz:
y una función para establecer parámetros para publicar datos en el servidor (en MainActivity):
Y encontré Retrofit más rápido que volea en mi caso.
fuente