I'm trying to fetch some data using POST method. The URL is sending proper response, which is of course an Object. When I try to access the responseJSON which is a property of the response Object, it returns undefined. But when try to do the same thing on console, it works fine! objectName.responseJSON works properly in this case. But why it's not working the same way while I use it in my code?
Also, on a button click, which changes a little bit of the fetched data, it again works fine. Means... that response Object and it's properties work fine on a button click but on $(document).ready or $(document).load. Why this is happening?
//Fetching data from URL
oldData = $.post("{$_url}reports/get_all_transactions", {
'startDate': document.getElementById('startDate').value,
'endDate': document.getElementById('endDate').value
});
//Printing the result on Console
$(document).ready(function() {
console.log(oldData); //This prints the whole response object
console.log(oldData.responseJSON); //This outputs 'undefined'
})
I even tried JSON.parse(), JSON.stringify() and their combination on the object. But on Stringify, it's just converting the first property of the object into String and not the whole object. And the Parse method returns error.
Then how can I access my desired object property?
Better to use native fetch instead, no need for jQuery these days.
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
startDate : document.getElementById('startDate').value,
endDate : document.getElementById('endDate').value
})
});
const text = await response.text();
const obj = JSON.parse(text)
Docs: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Related
This question already has answers here:
Using Fetch API to Access JSON
(3 answers)
Closed 1 year ago.
I currently have my own api i am trying to send and retrieve data from.
In the api I am trying to send an object to the front-end using something like res.send({data: 1}).
I am easily able to access this data using postman but when trying to fetch the data using - well - fetch, i have no way to acess it. the way I try to fetch it is as follows:
const response = await fetch("http://localhost:2000/user/login", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(user),
});
And logged response looks like this:
body: (...)
bodyUsed: false
headers: Headers
[[Prototype]]: Headers
ok: true
redirected: false
status: 200
type: "cors"
url: "http://localhost:2000/user/login"
[[Prototype]]: Response
The {data: 1} object is nowhere to be found and i have no clue how to access it.
Is this the wrong way to go about retrieving and sending data from and to an api or am i just overlooking something?
What would the best way to transfer data like this be then?
Thanks in advance!
Ps: the {data: 1} is just an example and the real way i would use this at the moment would be to fetch data from an express session cookie.
fetch() returns a promise whose resolved value gets you the status and headers of the response. You are awaiting that promise so you do get that info. But to read the actual body of the response, you need to make another call to response.json() that returns another promise:
const response = await fetch("http://localhost:2000/user/login", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(user),
});
// read the body of the response
const data = await response.json();
console.log(data);
I'm trying to remove jQuery from some code. I only use it for POST operations so I want to drop it and use fetch() instead. But I can't get fetch() to work using the same data. The php file is working OK, it is just not receiving the data
This sets up the test data for both test cases below:
var toPostObj = new(Object);
toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];
This works using jQuery:
$.post('toMariaDB.php', { // url
data: toPostObj
}, function(data2, status, jqXHR) {
console.log ("data2",data2);
});
This does not work using fetch():
fetch("toMariaDB.php", {
method: "POST",
body: toPostObj, // using JSON.stringify(toPostObj) also doesn't work
headers: { "Content-type": "application/text; charset=UTF-8" }
})
.then(response => response.text())
.then(text => console.log(text))//;
.catch(error => {
console.error(error)
})
For debugging purposes, toMariaDB.php writes out a log file of the data it receives and any other messages from toMariaDB.
Running the jQuery code writes this to the log file:
toMariaDB: I've ARRIVED
in toMariaDB 1=>Array
(
[action] => update+file
[arrays] => Array
(
[0] => Array
(
[0] => 2020-12-28
[1] => 23:20:56
[2] => Trying from ztest
[3] => 9.jpg
)
)
)
which is what toMariaDB.php expects.
But the fetch() version writes this:
toMariaDB: I've ARRIVED
in toMariaDB 1=>
The result for fetch() is the same whether I use
body: toPostObj,
or
body: JSON.stringify(toPostObj),
I've used
headers: { "Content-type": "application/text; charset=UTF-8" }
since toMariaDB.php returns text and, as I understand it, headers describes what is returned
but just in case I had misunderstood, I tried
headers: { "Content-type": "application/json; charset=UTF-8" }
as well, but that didn't work either.
How can I format the body so that it arrives at toMariaDB.php in the same form as with jQuery? I.e.
toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];
Thanks for any help.
EDIT
As suggested by #T.J.Crowder, (thanks for pointing me at that) here's what the Network tab shows as the Request Payload when running with jQuery:
data[action]: update+file
data[arrays][0][]: 2020-12-28
data[arrays][0][]: 23:20:56
data[arrays][0][]: Trying from ztest
data[arrays][0][]: 9.jpg
I don't understand why these don't show as data[arrays][0][0], etc., but it works.
(It's a 2D array because toMariaDB.php has to be able to process multiple arrays.)
With fetch(), the Network tab Request Payload shows:
[object Object]
From the documentation we can see that...
When data is an object, jQuery generates the data string from the object's key/value pairs unless the processData option is set to false. For example, { a: "bc", d: "e,f" } is converted to the string "a=bc&d=e%2Cf". If the value is an array, jQuery serializes multiple values with same key based on the value of the traditional setting (described below). For example, { a: [1,2] } becomes the string "a%5B%5D=1&a%5B%5D=2" with the default traditional: false setting.
(It doesn't say so, but it does it recursively.)
Your code is sending an object with a single top-level property called data whose value is your toPostObj, which in turn has properties with string and array values. It ends up sending a POST body that looks like this:
data%5Baction%5D=update%2Bfile&data%5Barrays%5D%5B0%5D%5B%5D=2020-12-28&data%5Barrays%5D%5B0%5D%5B%5D=23%3A20%3A56&data%5Barrays%5D%5B0%5D%5B%5D=Trying+from+ztest&data%5Barrays%5D%5B0%5D%5B%5D=9.jpg
...which is these parameters:
data[action]: update+file
data[arrays][0][]: 2020-12-28
data[arrays][0][]: 23:20:56
data[arrays][0][]: Trying from ztest
data[arrays][0][]: 9.jpg
You can replicate that with a URLSearchParams object like this:
var toPostObj = new URLSearchParams();
toPostObj.append("data[action]", "update+file");
toPostObj.append("data[arrays][0][]", "2020-12-28");
toPostObj.append("data[arrays][0][]", "23:20:56");
toPostObj.append("data[arrays][0][]", "Trying from ztest");
toPostObj.append("data[arrays][0][]", "9.jpg");
fetch("foo", {
method: "POST",
body: toPostObj
})
// ...
URLSearchParams will handle the URI-escaping etc. for you.
I think you'd have the best experience using this:
fetch("toMariaDB.php", {
method: "POST",
body: JSON.stringify(toPostObj),
headers: {
"Content-type": "application/json",
},
})
And doing json_decode on the PHP side.
If you want to exactly replicate what jQuery does, you'll have to look into the network tab as it can differ... but most likely it's using application/x-www-form-urlencoded as the content type. Best way to replicate that is to populate a FormData object which is still quite a hassle when you have arrays, especially nested arrays.
console.log("data ", data); // returns an object in JSON format {propertyName: propertyValue}
dataString = JSON.stringify(dataString); //correctly stringified json
let response = await fetch('updateRecevingEntry.php',
{
method:'POST',
headers: {'Content-Type':'application/json'},
body: dataString
}).then(response=>response.json());
however I get back an undefined index on the php side.
where the php is:
$matkey = $_POST['materialKey'];
returns
<b>Notice</b>: Undefined index: materialKey in <b>path/updateRecevingEntry.php</b> on line <b>3</b><br />
for all the data... none of it is getting caught.
so why is the _POST['propertyName'] not catching the stringData from the body?
I've tried a few variations, such as sending the data instead of the string data messing with the header, but I can't seem to figure out how to send the payload such that _POST['propertyName'] catches the data in the body.
I was using $.ajax from jquery before, and it was working: but I'm in the process of refactoring that out.
the Fetch api is new to me. where am I going wrong. I also don't want to parse a json object on the php side.
after reading one of the answers, I got it to work in one case,
but
let response = await fetch('updateRecevingEntry.php',
{
method:'POST',
headers: {'Content-Type':'application/json'},
body: sendData
}).then(response=>response.json());
and the php
$postData = json_decode(file_get_contents("php://input"), true);
var_dump($postData);
just returns a big fat NULL.
Edit two: turns out it just needs to actually be encoded via JSON.stringify(sendData). Since the. It works as expected.
The first thing I've noticed is that you're not using the right variable (you're using stringData instead of dataString):
dataString = JSON.stringify(dataString); //correctly stringified json
let response = await fetch('updateRecevingEntry.php', {
method:'POST',
headers: {'Content-Type':'application/json'},
body: dataString
}).then(response=>response.json());
Though you shouldn't need to stringify it as you're sending it with json headers.
Additionally, have you tried instead of $_POST, using php://input?
From PHP.net:
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data".
So you would use it like so:
$postData = json_decode(file_get_contents("php://input"), true);
$matkey = $postData['materialKey'];
This reads the body of the POST request as a JSON string then converts it to a PHP array.
I am working on converting angularjs application to react and decided to use axios for API request.
Everything work fine except some response body with JSON type but the boolean values are string type not boolean. It works fine with angularJs $http but some of endpoints returns like that.
The modules are AngularJs + Typescript 2.9.1 + axios 0.19.0
let request = Axios({
...requestConfig,
url: resource, method: 'get', responseType: 'json'
}).then(response => response);
and the response body is
{
some: "true"
}
but I am excepting
{
some: true
}
Any ideas?
[UPDATE] as Phil pointed out, Boolean('false') does not work. I updated the code to something that will work for 'true' and 'false', but a more complex function is needed if you want to cover all possibilities.
If the response by the API exactly looks like this:
{
"some": "true"
}
Then axios is not doing anything wrong. It's dangerous for a library to automagically parse values as they see fit, just look at how Json.NET handles values that they think look like Datetime.
If the payload returned by the API looks exactly like this:
{
"some" : true
}
Then axios should parse it as a boolean directly.
What I propose you do, is to always parse the value as a boolean, even if it is already one:
let request = await Axios({...requestConfig,
url: resource, method: 'get', responseType: 'json'
});
let someValue = String(request.data.some) == "true";
This will work for Boolean("true") as well as Boolean(true).
This is the json result I get from my controller
{"data":"Sunday"}
The data can say any day of the week (Sunday, Monday, etc...)
On success I want to do this in ajax call
success: function(Response){
var myresponse = Response.data;
alert(myresponse);
}
However, it gives me undefined.
If you are sure that you are getting a JSON response from the server, you can make use of the Ext.JSON class to decode the JSON.
You can use the decode() method to convert a string to an object. Then you should be able to easily access it.
Example:
var jsonObject = Ext.JSON.decode(Response.responseText);
var myData = jsonObjet.data;
If you are using jQuery to load this string you could just use $.getJSON which will automatically parse the string and pass the object as the return value to the 'success' function.
try to use a
console.log(Response);
to check the content of Response
It might be considering your response to be a string. I would do something like this:
success: function(Response){
alert(typeof Response);
var myresponse = Response.data;
alert(myresponse);
}
If it tells you that Response is string, you need to make sure that your framework knows you are getting back JSON. For instance with jquery it might be $.getJSON().