1

necesito pasar un objeto por metodo post:

 <script>
 function postdata(){
 const formData = new URLSearchParams();
 var prueba = [{nombre: "doble proteína", cantidad: "1"},{nombre: 
 "doble proteína con mixta", cantidad: "4"}]
 formData.append('adicionar', prueba);
 fetch('/pedidos/done',
 {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form- 
 urlencoded;charset=UTF-8'
      },
        body: formData.toString(),
        json: true
    });
 };
 </script>

necesito pasar el objeto prueba pero no funciona parece ser que si es solo un array lo hace correctamente pero necesito que envíe un objeto. gracias cualquier ayuda es agradecida :)

alejogon
  • 109
  • 1
  • 9

1 Answers1

3

Para enviar un "objeto" usando la API Fetch, debes realizar algunas configuraciones en las cabeceras de la petición http, para indicar que estás enviando una cadena en formato JSON.

Objeto !== JSON

Debemos aclarar que los términos objeto y JSON no son intercambiables. Es decir no es correcto decir: objeto JSON (excepto cuando te refieres al objeto global JSON de Javascript), tampoco es correcto referirse a una cadena en formato JSON como un objeto y tampoco es correcto referirse a un objeto de JavaScript como JSON.

Dicho esto, lo que se envía realmente es una cadena en formato JSON, por lo tanto debemos realizar un proceso muy conocido en JavaScript que convierte un objeto en una cadena en formato JSON. Para esto usaremos el método stringify() del objeto global JSON.

// un objeto muy básico:
const objeto = {
  prop: 'valor',
  anotherProp: 'valor'
}

// una cadena JSON creada a partir del objeto

const myJSONString = JSON.stringify(objeto);

console.log(`'objeto' es de tipo: ${typeof objeto}.`);
console.log(objeto);
console.log(`'myJSONString' es de tipo: ${typeof myJSONString}`);
console.log(myJSONString);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Ya tenemos la forma de obtener una cadena JSON a partir de un objeto de Javascript.

Cabeceras, o el dolor de cabeza de las peticiones http

Ahora vamos a ver el tema de las cabeceras, que a veces causan un poco de complicación, simplemente porque se nos olvida que las mismas existen o porque no damos con la cabecera adecuada.

El estándar http nos provee de una serie de cabeceras para trabajar durante el intercambio de datos.

Javascript nos provee de un constructor para crear un objeto Headers y así poder trabajar con la API Fetch. Este constructor es el método Headers().

Podemos crear un objeto Headers de la siguiente forma:

// podemos crear un objeto Headers vacío
let myCustomHeaders = new Headers();
// ahora le añadimos un par clave/valor a nuestro objeto
myCustomHeaders.append('Content-Type', 'text/plain');

console.log(myCustomHeaders.has('Content-Type'));
console.log(myCustomHeaders.get('Content-Type'));

// también podemos crear un objeto Headers pasando un
// par clave/valor inicial, o varios si es requerido
let myNewCustomHeaders = new Headers({
  'Content-Type': 'application/json'
});

console.log(myNewCustomHeaders.has('Content-Type'));
console.log(myNewCustomHeaders.get('Content-Type'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Para este caso en particular nos interesa incluir un tipo de cabecera Content-Type cuyo valor será una cadena con el formato aceptado por el estándar IANA para tipos MIME. La misma es application/json.

La SOLICITUD

Ahora falta escribir la solicitud. Para ello usaremos el constructor Request() que nos permitirá crear un objeto Request que podremos usar con la API Fetch.

// esqueleto de la solicitud
const laSolicitud = new Request(
  laURL,
  {
    method: 'POST',
    headers: losHeaders,
    body: JSON.stringify(elObjeto)
  }
);

Esta sería la estructura básica de nuestra solicitud para ser usada con la API fecth. Si todo va bien del lado servidor, debemos obtener una respuesta acorde a nuestra solicitud.

Veamos un ejemplo:

const elObjeto = {
  clave: 'valor'
}

const lasCabeceras = new Headers({
  'Accept': 'application/json',
  'Content-type': 'application/json'
});


const laURL = 'https://httpbin.org/post';

const laSolicitud = new Request(
  laURL,
  {
    method: 'POST',
    headers: lasCabeceras,
    //mode: 'no-cors',
    body: JSON.stringify(elObjeto)
  }
);

fetch(laSolicitud)
  .then((response) => {
    return response.json();
  })
  .then((json) => {
    // podemos ver el objeto pasado en la clave 'data'
    console.log(`El tipo de 'json.data' es: ${typeof json.data}`);
    console.log(json.data);
    // claro está que viene como cadena de texto
    // si deseamos verlo como objeto, habrá que
    // usar JSON.parse()
    let objeto = JSON.parse(json.data);
    console.log(`El tipo de 'objeto' es: ${typeof objeto}`);
    console.log(objeto);
  })
  .catch((error) => {
    console.log('Uuuuups');
    console.log(error.message);
  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

Puedes observar que he añadido la cabecera Accept a mi solicitud, para indicarle al servidor el tipo de respuesta que puedo aceptar. En este caso le indico que puedo aceptar un tipo MIME application/json.

Actualización

La RESPUESTA

La respuesta que recibimos de parte del servidor dependerá de la forma en que el mismo esté implementado.

¿Y cómo saberlo?

Si de antemano sabemos el tipo de respuesta enviado por el servidor, es fácil seguir un curso. Pero si no sabemos lo que va a responder, entonces la cosa se complica un poco.

Una forma de saber el tipo de respuesta devuelta es analizando las cabeceras recibidas. En particular podemos buscar el tipo 'content-type', y leer su valor.

Además, el objeto Response nos provee del método text(), mediante el cual podremos obtener el contenido de la respuesta en modo texto.

Por ejemplo, (aquí uso un método GET a una ruta de httpbin.org que de antemano sé que me responderá con un html):

const lasCabeceras = new Headers({
  'Accept': 'application/json, text/html' // notemos que indico el tipo MIME aceptado separado por comas en caso de ser más de 1
});

const laURL = 'https://httpbin.org/html';

const laSolicitud = new Request(
  laURL,
  {
    method: 'GET',
    headers: lasCabeceras,
  }
);

fetch(laSolicitud)
  .then((response) => {
    return response.text();
  })
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log('Uuuuups');
    console.log(error.message);
  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

Como puedes observar el texto recibido viene en formato html, y el primer carácter del mismo es <. En tu comentario indicas que al usar el primer ejemplo recibes un error:

Unexpected token < in JSON at position 0

Es claro que en tu caso, el servidor no está devolviendo un JSON, sino un documento html (o un xml), dado que el error indica que el primer carácter encontrado en la respuesta es <. Por lo tanto, en tu caso particular, debes usar el método text(), para obtener la respuesta.

Con esto ya tienes una forma de enviar un objeto básico usando fetch.

Puedes leer el siguiente post que explica con más detalle el uso de la API Fetch.

Mauricio Contreras
  • 13,660
  • 3
  • 18
  • 40