How can I send JSON data from Javascript in the browser, to a server and have PHP parse it there?
I've gotten lots of information here so I wanted to post a solution I discovered.
The problem: Getting JSON data from Javascript on the browser, to the server, and having PHP successfully parse it.
Environment: Javascript in a browser (Firefox) on Windows. LAMP server as remote server: PHP 5.3.2 on Ubuntu.
What works (version 1):
1) JSON is just text. Text in a certain format, but just a text string.
2) In Javascript, var str_json = JSON.stringify(myObject) gives me the JSON string.
3) I use the AJAX XMLHttpRequest object in Javascript to send data to the server:
request= new XMLHttpRequest()
request.open("POST", "JSON_Handler.php", true)
request.setRequestHeader("Content-type", "application/json")
request.send(str_json)
[... code to display response ...]
4) On the server, PHP code to read the JSON string:
$str_json = file_get_contents('php://input');
This reads the raw POST data. $str_json now contains the exact JSON string from the browser.
What works (version 2):
1) If I want to use the "application/x-www-form-urlencoded" request header, I need to create a standard POST string of "x=y&a=b[etc]" so that when PHP gets it, it can put it in the $_POST associative array. So, in Javascript in the browser:
var str_json = "json_string=" + (JSON.stringify(myObject))
PHP will now be able to populate the $_POST array when I send str_json via AJAX/XMLHttpRequest as in version 1 above. Displaying the contents of $_POST['json_string'] will display the JSON string. Using json_decode() on the $_POST array element with the json string will correctly decode that data and put it in an array/object.
The pitfall I ran into:
Initially, I tried to send the JSON string with the header of application/x-www-form-urlencoded and then tried to immediately read it out of the $_POST array in PHP. The $_POST array was always empty. That's because it is expecting data of the form yval=xval&[rinse_and_repeat]. It found no such data, only the JSON string, and it simply threw it away. I examined the request headers, and the POST data was being sent correctly.
Similarly, if I use the application/json header, I again cannot access the sent data via the $_POST array. If you want to use the application/json content-type header, then you must access the raw POST data in PHP, via php://input, not with $_POST.
References:
1) How to access POST data in PHP: How to access POST data in PHP?
2) Details on the application/json type, with some sample objects which can be converted to JSON strings and sent to the server: http://www.ietf.org/rfc/rfc4627.txt
Javascript file using jQuery (cleaner but library overhead):
$.ajax({
type: 'POST',
url: 'process.php',
data: {json: JSON.stringify(json_data)},
dataType: 'json'
});
PHP file (process.php):
directions = json_decode($_POST['json']);
var_dump(directions);
Note that if you use callback functions in your javascript:
$.ajax({
type: 'POST',
url: 'process.php',
data: {json: JSON.stringify(json_data)},
dataType: 'json'
})
.done( function( data ) {
console.log('done');
console.log(data);
})
.fail( function( data ) {
console.log('fail');
console.log(data);
});
You must, in your PHP file, return a JSON object (in javascript formatting), in order to get a 'done/success' outcome in your Javascript code. At a minimum return/print:
print('{}');
See Ajax request return 200 OK but error event is fired instead of success
Although for anything a bit more serious you should be sending back a proper header explicitly with the appropriate response code.
Simple example on JavaScript for HTML input-fields (sending to server JSON, parsing JSON in PHP and sending back to client) using AJAX:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<body>
<div align="center">
<label for="LName">Last Name</label>
<input type="text" class="form-control" name="LName" id="LName" maxlength="15"
placeholder="Last name"/>
</div>
<br/>
<div align="center">
<label for="Age">Age</label>
<input type="text" class="form-control" name="Age" id="Age" maxlength="3"
placeholder="Age"/>
</div>
<br/>
<div align="center">
<button type="submit" name="submit_show" id="submit_show" value="show" onclick="actionSend()">Show
</button>
</div>
<div id="result">
</div>
<script>
var xmlhttp;
function actionSend() {
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var values = $("input").map(function () {
return $(this).val();
}).get();
var myJsonString = JSON.stringify(values);
xmlhttp.onreadystatechange = respond;
xmlhttp.open("POST", "ajax-test.php", true);
xmlhttp.send(myJsonString);
}
function respond() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById('result').innerHTML = xmlhttp.responseText;
}
}
</script>
</body>
</html>
PHP file ajax-test.php :
<?php
$str_json = file_get_contents('php://input'); //($_POST doesn't work here)
$response = json_decode($str_json, true); // decoding received JSON to array
$lName = $response[0];
$age = $response[1];
echo '
<div align="center">
<h5> Received data: </h5>
<table border="1" style="border-collapse: collapse;">
<tr> <th> First Name</th> <th> Age</th> </tr>
<tr>
<td> <center> '.$lName.'<center></td>
<td> <center> '.$age.'</center></td>
</tr>
</table></div>
';
?>
PHP has a built in function called json_decode(). Just pass the JSON string into this function and it will convert it to the PHP equivalent string, array or object.
In order to pass it as a string from Javascript, you can convert it to JSON using
JSON.stringify(object);
or a library such as Prototype
This is a summary of the main solutions with easy-to-reproduce code:
Method 1 (application/json or text/plain + JSON.stringify)
var data = {foo: 'blah "!"', bar: 123};
var xhr = new XMLHttpRequest();
xhr.open("POST", "test.php");
xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { console.log(xhr.responseText); } }
xhr.setRequestHeader("Content-type", "application/json") // or "text/plain"
xhr.send(JSON.stringify(data));
PHP side, you can get the data with:
print_r(json_decode(file_get_contents('php://input'), true));
Method 2 (x-www-form-urlencoded + JSON.stringify)
var data = {foo: 'blah "!"', bar: 123};
var xhr = new XMLHttpRequest();
xhr.open("POST", "test.php");
xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { console.log(xhr.responseText); } }
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("json=" + encodeURIComponent(JSON.stringify(data)));
Note: encodeURIComponent(...) is needed for example if the JSON contains & character.
PHP side, you can get the data with:
print_r(json_decode($_POST['json'], true));
Method 3 (x-www-form-urlencoded + URLSearchParams)
var data = {foo: 'blah "!"', bar: 123};
var xhr = new XMLHttpRequest();
xhr.open("POST", "test.php");
xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { console.log(xhr.responseText); } }
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(new URLSearchParams(data).toString());
PHP side, you can get the data with:
print_r($_POST);
Note: https://caniuse.com/#search=URLSearchParams
There are 3 relevant ways to send Data from client Side (HTML, Javascript, Vbscript ..etc) to Server Side (PHP, ASP, JSP ...etc)
1. HTML form Posting Request (GET or POST).
2. AJAX (This also comes under GET and POST)
3. Cookie
HTML form Posting Request (GET or POST)
This is most commonly used method, and we can send more Data through this method
AJAX
This is Asynchronous method and this has to work with secure way, here also we can send more Data.
Cookie
This is nice way to use small amount of insensitive data. this is the best way to work with bit of data.
In your case You can prefer HTML form post or AJAX. But before sending to server validate your json by yourself or use link like http://jsonlint.com/
If you have Json Object convert it into String using JSON.stringify(object), If you have JSON string send it as it is.
using JSON.stringify(yourObj) or Object.toJSON(yourObj) last one is for using prototype.js, then send it using whatever you want, ajax or submit, and you use, as suggested, json_decode ( http://www.php.net/manual/en/function.json-decode.php ) to parse it in php. And then you can use it as an array.
I recommend the jquery.post() method.
<html>
<script type="text/javascript">
var myJSONObject = {"bindings": 11};
alert(myJSONObject);
var stringJson =JSON.stringify(myJSONObject);
alert(stringJson);
</script>
</html>
You can easily convert object into urlencoded string:
function objToUrlEncode(obj, keys) {
let str = "";
keys = keys || [];
for (let key in obj) {
keys.push(key);
if (typeof (obj[key]) === 'object') {
str += objToUrlEncode(obj[key], keys);
} else {
for (let i in keys) {
if (i == 0) str += keys[0];
else str += `[${keys[i]}]`
}
str += `=${obj[key]}&`;
keys.pop();
}
}
return str;
}
console.log(objToUrlEncode({ key: 'value', obj: { obj_key: 'obj_value' } }));
// key=value&obj[obj_key]=obj_value&
I found easy way to do but I know it not perfect
1.assign json to
if you JSON is
var data = [
{key:1,n: "Eve"}
,{key:2,n:"Mom"}
];
in ---main.php ----
<form action="second.php" method="get" >
<input name="data" type="text" id="data" style="display:none" >
<input id="submit" type="submit" style="display:none" >
</form>
<script>
var data = [
{key:1,n: "Eve"}
,{key:2,n:"Mom"} ];
function setInput(data){
var input = document.getElementById('data');
input.value = JSON.stringify(data);
var submit =document.getElementById('submit');
//to submit and goto second page
submit.click();
}
//call function
setInput(data);
</script>
in ------ second.php -----
<script>
printJson();
function printJson(){
var data = getUrlVars()["data"];
//decode uri to normal character
data = decodeURI(data);
//for special character , / ? : # & = + $ #
data = decodeURIComponent(data);
//remove " ' " at first and last in string before parse string to JSON
data = data.slice(1,-1);
data = JSON.parse(data);
alert(JSON.stringify(data));
}
//read get variable form url
//credit http://papermashup.com/read-url-get-variables-withjavascript/
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
</script>
Related
I need to POST a JSON ecoded string using the following parameters:
{"params":"query=ADDQUERY&hitsPerPage=6&filters=type%3Aartists"}
I have;
An endpoint URL to query;
An input search box and a search button to trigger the query. I need to replace ADDQUERY with the user input.
Can anyone shed some light on calling this info with JSON POST?
Like this,
you can copy and paste this, just make sure to change the target url, and the input boxes querySelector , if it has an ID use '#' + the box id.
Edited your fiddle. Here's the full code.
<div class="bodyparent">
<div class="searchbar">
<div class="searchbar_inner">
<div class="searchleft">
<image onclick="search()" src ="search.png"/>
</div>
<div class="searchright">
<input onchange="search()" id="searchinput" type="text" placeholder="Search...">
</div>
</div>
</div>
<div class="searchresults">
</div>
<script>
function search(){
var box = document.querySelector("#searchinput");
var json = { "params" : "query=" + box.value + "&hitsPerPage=" + 6 + "&filters=type_artists"};
var postData = JSON.stringify(json);
//this is the string you requested above.
var x = new XMLHttpRequest();
x.open("POST" , "https://ufhsub9629-dsn.algolia.net/1/indexes/search/query?x-algolia-application-id=UFHSUB9629&x-algolia-api-key=69ed687a250f4c895cc73f6ee142a42e" , true);
x.onreadystatechange = function(){
if(x.status == 200 && x.readyState == 4){
//do whatever here
}
}
x.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
x.send(JSON.stringify(json));
}
</script>
Its definitely working buddy:
I understand that you are trying to build your query using just PHP. You could look into using CURL to build the URL and send the request to a site or you could just encode the string with JS and redirect the page with the new URL.http://codular.com/curl-with-php A better option would be to send the request with AJAX and prevent a page refresh. Hope this helps. http://jsfiddle.net/codedcontainer/xpvt214o/287107/
$('form#artistForm').on('submit', function(e){
e.preventDefault();
var inputVals = $(this).serializeArray();
var singleInputVal = returnSingleInputVal('search', inputVals);
var queryObj = buildAjaxObject(singleInputVal);
sendAjaxRequest('/echo/json', queryObj);
});
function buildAjaxObject(searchQuery){
var dataObject = {
query :searchQuery,
hitsPerPage: 6,
filters: ['artist', 'asc']
}
return dataObject;
}
function sendAjaxRequest(url, dataObject){
$.post(url, JSON.stringify(dataObject), function(data){
$('#resultString').text(data);
});
}
function returnSingleInputVal(inputName, inputArray){
for (var a = 0; a <= inputArray.length -1; a++){
if ( inputArray[a].name == inputName){
return inputArray[a].value;
}
}
}
My code works fine when I run the php script without ajax as a GET request. I get prompted to download the rendered pdf and all is well. However, I need to use ajax because I need to send more info from an html page to the php script than can be handled in a GET request.
What do I need to put into my ajax to make this work?
Thanks
js
function makePDF()
{
var x;
if(window.event) // IE8 and earlier
{
x=event.keyCode;
}
else if(event.which) // IE9/Firefox/Chrome/Opera/Safari
{
x=event.which;
}
keychar=String.fromCharCode(x);
alert(keychar);
if (keychar == 'p' || keychar == 'P')
{
var charSheetHTML = characterSheet.innerHTML;
$.ajax({
url: 'pdf.php',
data: {'charactersheet': charSheetHTML,},
type: 'post',
success: function (data) {**WHAT_DO_I_PUT_HERE??**},
error: function (data) { alert("error\n" + data.toString()); }
});
}
}
pdf.php
<?php
include_once( "bxcharacter/PDFChar.php.inc" );
PDFChar();
?>
PDFChar.hph.inc
<?php
require_once('./tcpdf/tcpdf.php');
function PDFChar(){
$pdf = new TCPDF();
$pdf->AddPage('P');
$pdf->writeHTML($_POST['charactersheet']);
$pdf->Output("character.pdf", 'D');
}
?>
This is not an ajax solution, but you can send your data with this way and if no error occurs, your page will not change.
Create a form element with inputs hidden which contains your data you want to send:
example format:
<form id="myForm" method="GET" action="pdf.php">
<input type="hidden" name="data1" type="hidden" value="your JSON.stringify() data">
</form>
js code (call these where your ajax request is):
var myForm = '<form id="myForm" method="GET" action="pdf.php">';
myForm += '<input type="hidden" name="data1" type="hidden" value="JSON.stringify() data">';
myForm += '</form>';
$("body").append(myForm); // temporarily appending
$("#myData-form").submit(); // submitting form with data
$("#myData-form").remove(); // remove form after submit
And as you said, force download will force file to download and page will remain same. However, if an error occurs, your page will change of course.
I don't know whether this is an effective way or not but in my case, this does the trick.
Old question, but I was trying to do something similar with Laravel PDF extension, and stumbled across this question. I did successfully do this asynchronously with the help of a nice blog post
https://nehalist.io/downloading-files-from-post-requests/
https://github.com/nehalist/download-post-requests
The using the form method, like the previous answer works fine too, but maybe this will help anyone else trying to achieve this with AJAX. The author's XMLHttpRequest method worked great for me!
The code that worked for me (almost verbatim from the blog post) ->
document.getElementById('exportpdf').addEventListener('click', function () {
var request = new XMLHttpRequest();
request.open('POST', '/your/post/endpoint/here', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';
request.onload = function() {
if(request.status === 200) {
var disposition = request.getResponseHeader('content-disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'file.pdf');
var blob = new Blob([request.response], { type: 'application/pdf' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};
I tried to get it to work with jQuery AJAX but failed, so I went with XMLHttpRequest. With jQuery, The download would work, but the content was always empty. I tried to do something like in this post -
https://keyangxiang.com/2017/09/01/HTML5-XHR-download-binary-content-as-Blob/
$.ajax does not support either arraybuffer or blob as its dataType. Thus we need write a beforeSend handler:
//setup ajax
$.ajaxSetup({
beforeSend:function(jqXHR,settings){
if (settings.dataType === 'binary'){
settings.xhr().responseType='arraybuffer';
settings.processData=false;
}
}
})
//use ajax now
$.ajax({
url:url,
dataType:"binary",
success:function(data){
console.log(data); //ArrayBuffer
console.log(new Blob([data])) // Blob
}
})
But never got it to work. Maybe someone smarter can figure out the jQuery method :)
Rooms are an array
window.location = "booking_status.php?array="+ JSON.stringify(rooms);
sending from javascript to php page
on php page url show full array value which are store in array in page address bar url
like that
http://localhost/zalawadi/booking_status.php?array=[{%22id%22:10,%22rate%22:100}]
I want to prevent this data which show in url %22id%22:10,%22rate%22:100
I am decoding on php page any other way to send array data from javascript to php page
The only way to send data to another page without showing them in the url is to use POST.
Basically, you can put your data into an invisible form input :
<form method="post" id="form" action="booking_status.php">
<input name="array" id="array" type="hidden" value="" />
</form>
Send
<script type="text/javascript">
function sendForm(){
document.getElementById('array').value = JSON.stringify(rooms);
document.getElementById('form').submit(); //fixed syntax
}
</script>
You can use a hidden form and the post method. Then you would use $_POST instead of $_GET.
<form action="script.php" onsubmit="this.firstChild.value=JSON.stringify(value);">
<input type="hidden" value="" />
Link text
</form>
You can use a POST request, however this would require generating and submitting a form:
// assuming `rooms` already defined
var frm = document.createElement('form'), inp = document.createElement('input');
frm.action = "booking_status.php";
frm.method = "post";
inp.type = "hidden";
inp.name = "array";
inp.value = JSON.stringify(rooms);
frm.appendChild(inp);
document.body.appendChild(frm);
frm.submit();
Why not just POST the data instead then?
For example, with jQuery:
$.ajax({
type: "POST",
url: "booking_status.php",
data: JSON.stringify(rooms),
success: // add success function here!
});
The advantage is you're not passing some horrific URL. As an added bonus, this example is also asynchronous, so the user doesn't see any refresh in their browser.
Non-Framework Version
If you don't wish to use jQuery, you can do this with pure Javascript, using the XMLHttpRequest object, like so:
var url = "get_data.php";
var param = JSON.stringify(rooms);
var http = new XMLHttpRequest();
http.open("POST", url, true);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
// Request has gone well. Add something here.
}
}
http.send(param);
I am trying to see the json data I sent to the server using XMLHttpRequest but it seems that the server is not receiving it, when I run the javascript the alert window will pop up but doesn't print anything. Anyone know how to solve this problem? Thanks
On the client side, Java script
var obj = {"action": "nothing"};
var jsonString = "jsonString=" + JSON.stringify(obj);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST","http://myserver/main.php",true);
xmlhttp.setRequestHeader("Content-type","application/json");
xmlhttp.setRequestHeader("Content-Length",jsonString.length);
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
alert(xmlhttp.responseText);
}
}
xmlhttp.send(jsonString);
On the server,php
if(isset($_POST['jsonString']))
echo $_POST['jsonString'];
You're sending JSON data, but the content-type is set to application/x-www-form-urlencoded. You should either send form/encoded data (var obj="action=nothing") or set the content-type to JSON (application/json)
James' solution works just fine, but if you are looking to send data using the application/json content type then you have to access the data in a different way.
For what you have server side,
if(isset($_POST['jsonString']))
echo $_POST['jsonString'];
change this (like James did):
xmlhttp.setRequestHeader("Content-type","application/json");
to
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
IF YOU WOULD LIKE TO USE THE application/json content type then you must change how you access it server side with:
$json_string = file_get_contents('php://input');
$json_object = json_decode($json_string);
echo $json_object->action;
This is working for me:
<html>
<head>
<script src='json.js'></script>
</head>
<body>
<script>
var obj = {"action": "nothing"};
var jsonString = "jsonString=" + JSON.stringify(obj);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST","whereIPutThePHP.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-Length",jsonString.length);
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState === 4 && (xmlhttp.status === 200)){
alert(xmlhttp.responseText);
}
}
xmlhttp.send(jsonString);
</script>
</body>
</html>
I finally succeeded in using Ajax to get SOMETHING sent from one page to another! What I'm trying to do is pass an array from a PHP file to a Javascript file, and the Javascript file is receiving this in this.responseText:
<html>
<head>
<script type="text/javascript">
var jsonArray = ["chickens","horses","cows","werewolves","zombies","vampires","phantoms","U.S. Congressmen","performance artists","pieces of fencepost","barnhouses","robots","cyborgs"]
</script>
</head>
</html>
I tried running eval() and alerting the result, but no result appears. How do I successfully extract the array from this.responseText?
Edit Here is my function thus far:
/*
* Function: selectVictim
* Called from function laserOn()
*
* Selects a random victim from a list of victims
*
* #return String: victim
*/
function selectVictim()
{
var params = "url=queenofsheep.com/Sheep/victims.php";
var request = new ajaxRequest();
request.open("POST", "victims.php", true);
request.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
request.setRequestHeader("Content-Length", params.length);
request.setRequestHeader("Connection", "close");
request.onreadystatechange = function ()
{
if (this.readyState == 4)
{
if (this.status == 200)
{
if (this.responseText != null )
{
var vicArray = eval('('+this.responseText+')');
var numVic = Math.floor(Math.random() * (vicArray - 1));
alert(vicArray);
}
else alert("Ajax error: No data received");
}
else alert("Ajax Error: " + this.statusText);
}
}
request.send(params);
}
Second Edit The file containing the array (in PHP) is as follows:
<html>
<head>
<?php
$victims = array(
// Animals
"chickens",
"horses",
"cows",
// Supernatural
"werewolves",
"zombies",
"vampires",
"phantoms",
// Human
"U.S. Congressmen",
"performance artists",
// Inanimate, non-mechanical
"pieces of fencepost",
"barnhouses",
// Mechanical
"robots",
"cyborgs"
);
?>
<script type="text/javascript">
var jsonArray = <?php echo json_encode($victims); ?>
</script>
</head>
</html>
If your php page is returning all the text that you reported (with <html> etc...) then your output is not a JSON object, but an html page. Your response should contain only your serialized JSON object (and the proper http response headers)...
Once you have 'cleaned' your output you can use JSON2 library to parse your object:
http://www.json.org/js.html
var myObject = JSON.parse(myJSONtext);
That does not look like a proper JSON response from the server, because it contains HTML code and then a chunk of javascript. The response should contain only javascript code containing data, like
var data = ["chickens","horses","cows","werewolves","zombies"]";
You can then eval() the string and it will work.
As said above, eval() might be unsafe, so, if using jQuery, you can use the $.parseJSON function which is safe.
To return the JSON correctly, don't output HTML at all in the page, just do something like
<?php
$victims = ...; // fill array
echo json_encode($victims);
?>
You can use the library on json.org or use eval("(" + this.responseText + ")");
Generally you want to use a library to parse the JSON string instead of eval because eval is generally unsafe.