javascript - leer - Recuperar: datos POST json
leer json (11)
Estoy tratando de PUBLICAR un objeto JSON usando fetch .
Por lo que puedo entender, necesito adjuntar un objeto en cadena 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
el json echo de jsfiddle,
esperaría ver el objeto que he enviado (
{a: 1, b: 2}
) de regreso, pero esto no sucede: las herramientas de Chrome no muestran el JSON como parte de la solicitud , lo que significa que no se está enviando.
Con el soporte
async/await
ES2017, 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
Sin embargo, la pregunta es pedir un problema causado por
un error de Chrome solucionado hace mucho tiempo.
La respuesta original sigue.
Devtools de Chrome ni siquiera muestra el JSON como parte de la solicitud
Este es el verdadero problema aquí , y es un error con las herramientas de Chrome, solucionado 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
Creo que su problema es que
jsfiddle
puede procesar solicitudes
form-urlencoded
.
Pero la forma correcta de hacer una solicitud json es pasar
json
correcto como 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));
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 }
});
Tal como la solicitud de rizo
curl -v -X POST -H ''Content-Type: application/json'' -d ''@data.json'' ''/echo/json''
En caso de que el servicio remoto no acepte un archivo json como cuerpo, solo 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
});
Tal como la solicitud de rizo
curl -v -X POST -H ''Content-type: application/x-www-form-urlencoded'' -d ''@data.txt'' ''/echo/form''
Desde los motores de búsqueda, terminé en este tema para publicar datos que no son de Json con fetch, así que pensé en agregar esto.
Para los que
no son json
, no tiene que usar datos de formulario.
Simplemente puede configurar 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 del
body
, en lugar de escribirla como hice anteriormente, es usar bibliotecas.
Por ejemplo, la función
stringify
de
query-string
o paquetes
qs
.
Entonces usar esto se vería así:
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}
});
Después de pasar algunas veces, realice ingeniería inversa jsFiddle, tratando de generar carga útil: hay un efecto.
Por favor, observe (cuidado) en la
return response.json();
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
Esto está relacionado con
Content-Type
.
Como habrás notado en otras discusiones y respuestas a esta pregunta, algunas personas pudieron resolverlo configurando
Content-Type: ''application/json''
.
Desafortunadamente en mi caso no funcionó, mi solicitud POST todavía estaba vacía en el lado del servidor.
Sin embargo, si intenta con jQuery''s
$.post()
y está funcionando, la razón probablemente se deba a que jQuery usa
Content-Type: ''x-www-form-urlencoded''
lugar de
application/json
.
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 => {
...
})
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'');
});
La respuesta principal no funciona para PHP7, porque tiene una codificación incorrecta, pero podría encontrar 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, por ejemplo, de 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);
});
}
Puede ser útil para alguien:
Estaba teniendo el problema de que los datos de formulario no se enviaban para mi solicitud
En mi caso, fue una combinación de los siguientes encabezados que también estaban causando el problema y el tipo de contenido incorrecto.
Entonces 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"
Además, como otras respuestas sugieren que el encabezado Content-Type debe ser correcto.
Para mi solicitud, el encabezado correcto de Content-Type era:
"Content-Type": "application / x-www-form-urlencoded; charset = UTF-8"
En resumen, si sus datos de formulario no se adjuntan a la Solicitud, podrían ser sus encabezados. Intente llevar sus encabezados al mínimo y luego intente agregarlos uno por uno para ver si su problema está resuelto.
Si su carga útil JSON contiene matrices y objetos anidados, usaría
URLSearchParams
y el método
param()
jQuery.
fetch(''/somewhere'', {
method: ''POST'',
body: new URLSearchParams($.param(payload))
})
Para su servidor, esto se verá como un
<form>
HTML estándar que se está
POST
.
Tuve el mismo problema: no se envió ningún
body
de un cliente a un servidor.
Agregar el encabezado
Content-Type
resolvió para mí:
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''}
})