2

JavaScript Code:

$.ajax({
  type: "POST",
  url: "postTestingResult.php",
  data: {data: JSON.stringify(sendData)},
  dataType: "json",
  success: ajaxSuccess,
  error: ajaxError
});

PHP Code

$data = json_decode($_POST['data'], TRUE);

When I POST a complex data structure to the server, the outermost array is becoming a string. For example, the JavaScript object could be

var data = {"apps": [[1,2,3], [4,5,6]]}

Using JSON.stringify(data) this becomes

"{"apps": "[[1,2,3], [4,5,6]]"}" //As seen via console.log(data) in Chrome console

But after doing the json_decode($_POST['data'], TRUE) it becomes

array('apps' => '[[1,2,3], [4,5,6]]') //As seen via var_export($data, TRUE)

What's going on here? Why is the the array being converted to a string? To see the full JSON object and the full PHP object check out this pastebin with the two.

Any help is greatly appreciated, thank you.

UPDATE: Answer found I found the main culprit. I am also using Prototype.js and it was adding a toJSON method to the Object prototypes. Check out this SO question for details.

15
  • Looks like its a problem with JSON.stringify(), because that's when the nested arrays turn into a string. Still thinking about what may be happening, though. Commented Apr 4, 2014 at 1:24
  • 2
    So, sendData is an object literal? Have you tried sending it without JSON.stringify(). I didn't think you needed to JSONify POSTed object literal data. Commented Apr 4, 2014 at 1:28
  • @Darragh sendData is a complex data object. You can see the JSON.stringify version of it in the pastebin I linked to. You can think of it (without keys/data obviously) as: {[{[{[]},{[]}]},{[{[]},{[]}]}],{}} Commented Apr 4, 2014 at 1:32
  • 1
    @emab I'm not going to eval potentially malicious code. From php.net: "The eval() language construct is very dangerous because it allows execution of arbitrary PHP code." Besides the fact that 1) I shouldn't have to use eval for this, and 2) eval is slow! Commented Apr 4, 2014 at 1:34
  • 1
    @Sam you were on the right track! Check out the update I posted. tl;dr: I am also using Prototype.js in my code and it was adding a toJSON method to the Object prototype, which gets called by JSON.stringify if it exists Commented Apr 4, 2014 at 4:28

1 Answer 1

3

Try this. Send your data explicitly as application/json and don't wrap your sendData:

var sendData = {'apps': [[1,2,3], [4,5,6]]};

$.ajax({
  type: 'POST',
  url: 'postTestingResult.php',
  data: JSON.stringify(sendData), // don't wrap your JSONified object 
  contentType: 'application/json' // set application/json - default is x-form-urlencoded
});

Note the headers and data: application/json:

enter image description here

Of course, as you highlighted, the data will not be available in the $_POST superglobal now. However this is not an issue, a very common way to get the JSON data string is to read the raw post data via php://input:

$data = array();
$json = file_get_contents('php://input'); // read JSON from raw POST data

if (!empty($json)) {
    $data = json_decode($json, true); // decode
}

print_r($data);

Yields:

Array( 
  [apps] => Array ( 
    [0] => Array ( 
      [0] => 1 
      [1] => 2 
      [2] => 3 ) 
    [1] => Array ( 
      [0] => 4 
      [1] => 5 
      [2] => 6 
   ) 
))

Hope this helps :)

EDIT

Note that the PHP documentation states:

Note: A stream opened with php://input can only be read once; the stream does not support seek operations.

However, iirc this has or will change (possibly in PHP 5.6?). Don't quote me on that though, and for now, don't forget to assign the contents of that stream if you plan to reuse it!

Sign up to request clarification or add additional context in comments.

3 Comments

When you replicate the code above or when you are using the data in your pastebin? Can you check your request headers to inspect your request payload?
I forgot to reload the client code :P It comes through alright now I think, thanks! However, objects seem a bit weird. For example, how would I access app_id in the following? Array([permutation] => Array([permutation_id] => 66) [apps] => [{"app_id": 0, "app_name": "CvP"}])
The above seems like a dumb question, but when I do $data['apps'][0]['app_id'] I keep getting "PHP Warning: Illegal string offset 'app_id'"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.