Send JSON data from Javascript to PHP?

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>
 ';
?>

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.