Buscar: PUBLICAR datos json


Estoy intentando publicar un objeto JSON usando fetch.

Por lo que puedo entender, necesito adjuntar un objeto stringified al cuerpo de la solicitud, por ejemplo:

fetch("/echo/json/",
{
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    method: "POST",
    body: JSON.stringify({a: 1, b: 2})
})
.then(function(res){ console.log(res) })
.catch(function(res){ console.log(res) })

Al usar json echo de jsfiddle Esperaría ver el objeto que he enviado ({a: 1, b: 2}) de vuelta, pero esto no sucede - chrome devtools ni siquiera muestra el JSON como parte de la solicitud, lo que significa que no se está enviando.

Author: Razor, 2015-04-21

11 answers

Con ES2017 async/await soporte , así es como POST una carga JSON:

(async () => {
  const rawResponse = await fetch('https://httpbin.org/post', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({a: 1, b: 'Textual content'})
  });
  const content = await rawResponse.json();

  console.log(content);
})();

¿No puedes usar ES2017? Ver la respuesta de @vp_art usando promesas

La pregunta, sin embargo, está pidiendo un problema causado por un error de Chrome desde hace mucho tiempo fijo.
La respuesta original sigue.

Chrome devtools ni siquiera muestra el JSON como parte de la solicitud

Este es el verdadero problema aquí, y error con chrome devtools, corregido en Chrome 46.

Ese código funciona bien - está publicando el JSON correctamente, simplemente no se puede ver.

Esperaría ver el objeto que he enviado de vuelta

Eso no funciona porque ese no es el formato correcto para el eco de JSfiddle.

El código correcto es:

var payload = {
    a: 1,
    b: 2
};

var data = new FormData();
data.append( "json", JSON.stringify( payload ) );

fetch("/echo/json/",
{
    method: "POST",
    body: data
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })

Para los puntos finales que aceptan cargas útiles JSON, el código original es correcto

 237
Author: Razor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-14 19:21:10

Creo que su problema es que jsfiddle puede procesar form-urlencoded solo la solicitud.

Pero la forma correcta de hacer una solicitud json es pasar correct json como un cuerpo:

fetch('https://httpbin.org/post', {
  method: 'post',
  headers: {
    'Accept': 'application/json, text/plain, */*',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({a: 7, str: 'Some string: &=&'})
}).then(res=>res.json())
  .then(res => console.log(res));
 134
Author: vp_arth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-31 14:15:13

De los motores de búsqueda, terminé en este tema para los datos de publicación no json con fetch, así que pensé en agregar esto.

Para no json no es necesario utilizar datos de formulario. Simplemente puede establecer el encabezado Content-Type en application/x-www-form-urlencoded y usar una cadena:

fetch('url here', {
    method: 'POST',
    headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
    body: 'foo=bar&blah=1'
});

Una forma alternativa de construir esa cadena body, en lugar de escribirla como hice anteriormente, es usar bibliotecas. Por ejemplo, la función stringify de query-string o qs paquetes. Así que usando esto se vería como:

import queryString from 'query-string';
fetch('url here', {
    method: 'POST',
    headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
    body: queryString.stringify({for:'bar', blah:1}
});
 33
Author: Noitidart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-06 07:04:21

Después de pasar algunas veces, ingeniería inversa jsFiddle, tratando de generar carga útil - hay un efecto.

Por favor, ojo (cuidado) en línea return response.json(); donde la respuesta no es una respuesta - es una promesa.

var json = {
    json: JSON.stringify({
        a: 1,
        b: 2
    }),
    delay: 3
};

fetch('/echo/json/', {
    method: 'post',
    headers: {
        'Accept': 'application/json, text/plain, */*',
        'Content-Type': 'application/json'
    },
    body: 'json=' + encodeURIComponent(JSON.stringify(json.json)) + '&delay=' + json.delay
})
.then(function (response) {
    return response.json();
})
.then(function (result) {
    alert(result);
})
.catch (function (error) {
    console.log('Request failed', error);
});

JsFiddle: http://jsfiddle.net/egxt6cpz/46 / && Firefox > 39 & & Chrome > 42

 30
Author: Krzysztof Safjanowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-27 07:17:46

He creado una envoltura delgada alrededor de fetch() con muchas mejoras si está utilizando una API REST puramente json:

// Small library to improve on fetch() usage
const api = function(method, url, data, headers = {}){
  return fetch(url, {
    method: method.toUpperCase(),
    body: JSON.stringify(data),  // send it as stringified json
    credentials: api.credentials,  // to keep the session on the request
    headers: Object.assign({}, api.headers, headers)  // extend the headers
  }).then(res => res.ok ? res.json() : Promise.reject(res));
};

// Defaults that can be globally overwritten
api.credentials = 'include';
api.headers = {
  'csrf-token': window.csrf || '',    // only if globally set, otherwise ignored
  'Accept': 'application/json',       // receive json
  'Content-Type': 'application/json'  // send json
};

// Convenient methods
['get', 'post', 'put', 'delete'].forEach(method => {
  api[method] = api.bind(null, method);
});

Para usarlo tienes la variable api y 4 métodos:

api.get('/todo').then(all => { /* ... */ });

Y dentro de una función async:

const all = await api.get('/todo');
// ...

Ejemplo con jQuery:

$('.like').on('click', async e => {
  const id = 123;  // Get it however it is better suited

  await api.put(`/like/${id}`, { like: true });

  // Whatever:
  $(e.target).addClass('active dislike').removeClass('like');
});
 13
Author: Francisco Presencia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-02 06:15:03

Tuvo el mismo problema: no se envió body desde un cliente a un servidor.

Añadiendo Content-Type encabezado resuelto para mí:

var headers = new Headers();

headers.append('Accept', 'application/json'); // This one is enough for GET requests
headers.append('Content-Type', 'application/json'); // This one sends body

return fetch('/some/endpoint', {
    method: 'POST',
    mode: 'same-origin',
    credentials: 'include',
    redirect: 'follow',
    headers: headers,
    body: JSON.stringify({
        name: 'John',
        surname: 'Doe'
    }),
}).then(resp => {
    ...
}).catch(err => {
   ...
})
 8
Author: Green,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-21 07:27:12

Esto está relacionado con Content-Type. Como habrás notado en otras discusiones y respuestas a esta pregunta, algunas personas pudieron resolverla configurando Content-Type: 'application/json'. Desafortunadamente, en mi caso no funcionó, mi solicitud de POST seguía vacía en el lado del servidor.

Sin embargo, si intenta con el $.post() de jQuery y está funcionando, la razón es probablemente debido a que jQuery usa Content-Type: 'x-www-form-urlencoded' en lugar de application/json.

data = Object.keys(data).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])).join('&')
fetch('/api/', {
    method: 'post', 
    credentials: "include", 
    body: data, 
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
 5
Author: Marcus Lind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-27 08:52:05

Podría ser útil para alguien:

Estaba teniendo el problema de que formdata no se estaba enviando para mi solicitud

En mi caso, era una combinación de los siguientes encabezados que también estaban causando el problema y el Tipo de contenido incorrecto.

Así que estaba enviando estos dos encabezados con la solicitud y no estaba enviando los datos de formulario cuando eliminé los encabezados que funcionaban.

"X-Prototype-Version" : "1.6.1",
"X-Requested-With" : "XMLHttpRequest"

También como otras respuestas sugieren que el encabezado Content-Type debe ser correcto.

Para mi solicitud el encabezado Content-Type correcto fue:

"Content-Type": "application / x-www-form-urlencoded; charset = UTF-8"

Entonces, si su formdata no se adjunta a la Solicitud, podría ser sus encabezados. Intente llevar sus encabezados al mínimo y luego intente agregarlos uno por uno para ver si su problema está resuelto.

 2
Author: user_CC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-12 16:47:07

La respuesta superior no funciona para PHP7, porque tiene una codificación incorrecta, pero podría averiguar la codificación correcta con las otras respuestas. Este código también envía cookies de autenticación, que probablemente desee cuando se trata de, por ejemplo, foros PHP:

julia = function(juliacode) {
    fetch('julia.php', {
        method: "POST",
        credentials: "include", // send cookies
        headers: {
            'Accept': 'application/json, text/plain, */*',
            //'Content-Type': 'application/json'
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" // otherwise $_POST is empty
        },
        body: "juliacode=" + encodeURIComponent(juliacode)
    })
    .then(function(response) {
        return response.json(); // .text();
    })
    .then(function(myJson) {
        console.log(myJson);
    });
}
 1
Author: lama12345,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 04:25:21

Si su carga JSON contiene matrices y objetos anidados, usaría URLSearchParams y el método param() de jQuery.

fetch('/somewhere', {
  method: 'POST',
  body: new URLSearchParams($.param(payload))
})

Para su servidor, esto se verá como un HTML estándar <form> siendo POST ed.

 0
Author: Eric Sellin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-07 17:53:05

Creo que, no necesitamos analizar el objeto JSON en una cadena, si el servidor remoto acepta json en su solicitud, simplemente ejecute:

const request = await fetch ('/echo/json', {
  headers: {
    'Content-type': 'application/json'
  },
  method: 'POST',
  body: { a: 1, b: 2 }
});

Como la solicitud de curl

curl -v -X POST -H 'Content-Type: application/json' -d '@data.json' '/echo/json'

En caso de que el servidor remoto no acepte un archivo json como el cuerpo, simplemente envíe un formulario de datos:

const data =  new FormData ();
data.append ('a', 1);
data.append ('b', 2);

const request = await fetch ('/echo/form', {
  headers: {
    'Content-type': 'application/x-www-form-urlencoded'
  },
  method: 'POST',
  body: data
});

Como la solicitud de curl

curl -v -X POST -H 'Content-type: application/x-www-form-urlencoded' -d '@data.txt' '/echo/form'
 -1
Author: Daniel García,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-13 01:56:26