30

I am debugging this ajax for quite a time now. I have this on my jQUery file:

$("#typeForm").ajaxForm({
    success : function(html){
        alert(html);
}).submit();

This calls service.php, and within it I have this:

$data = array('upload_data' => $this->upload->data());
$str = "<div style='position:relative'><img src='/assets/ui/success.png' /><span style='position:relative;top:-15px;'>Nachricht empfangen!</span></div>";
echo json_encode(array('file_name' => $data['upload_data']['file_name'], 'prompt' => $str));

This won't work. But by replacing $str to $str = "HELLO WORLD"; the jQuery alerts what should I expected. What seems to be the problem?

EDIT:

Here is a screenie of the output:

enter image description here

It does alerts, but if I modify my jQuery into this:

$("#typeForm").ajaxForm({
    success : function(html){
        var obj = $.parseJSON(html);
        alert(obj);
}).submit();

Then it does nothing at all, even alerting.

I did a var_dump on the json_encode and here is the dump, it looks like a malformed JSON:

string(214) "{"file_name":"cde595988d386529909ce5a8fe3a6d6f.png","prompt":"<div style="position:relative;"><img src="\/assets\/ui\/success.png" \=""><span style="position:relative;top:-15px;">Nachricht empfangen!&lt;\/span&gt;&lt;\/div&gt;"}"
</span></div>

Here is the full content of service.php

class Service extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
    }
    public function index()
    {
        $filename = 'uploadfile';

        $config['upload_path'] = './uploads/temp';
        $config['allowed_types'] = 'jpg|png|gif|doc|docx|pdf|ppt|pptx|xls|xlsx|bmp';
        $config['max_size'] = '3072';
        $config['encrypt_name'] = TRUE;
        $config['remove_spaces'] = TRUE;

        $this->load->library('upload', $config);

        if (!$this->upload->do_upload($filename))
        {
            $error = array('error' => $this->upload->display_errors());
                    echo json_encode(array('error' => $error['error']));
        }
        else
        {
            $data = array('upload_data' => $this->upload->data());
            $file_name = $data['upload_data']['file_name'];
            //print_r($data);
            //echo json_encode(array('test' => "Hello World"));
            $str = "<div style='position:relative;'><img src='/assets/ui/success.png' /><span style='position:relative;top:-15px;'>Nachricht empfangen!</span></div>";
            $str2 = json_encode(array("file_name" => $file_name, "prompt" => $str));
            //var_dump($str2);
            exit(json_encode(array('file_name' => $data['upload_data']['file_name'], 'prompt' => $str)));
        }
    }
}
planet x
  • 1,509
  • 5
  • 26
  • 42

8 Answers8

102

I was having same problem with json_encode today. But after testing a lot I found the correct solution:

In PHP to encode the array or string:

json_encode($array, JSON_HEX_QUOT | JSON_HEX_TAG);

In JS to decode the same:

var d = $.parseJSON(content);
Andrew
  • 13,934
  • 8
  • 78
  • 93
Abhishek Sachan
  • 1,622
  • 2
  • 14
  • 28
  • 4
    Amazing answer! That's the way to do it. – Antonio Max Sep 19 '13 at 18:31
  • I was having the same issue but I was almost to the solution. I was using `json_encode($json, JSON_HEX_QUOT | JSON_HEX_APOS)`. Changing the `JSON_HEX_APOS` to `JSON_HEX_TAG` made my problems disappear! – MLK.DEV Mar 08 '14 at 03:46
  • 2
    Guys... you saved my life! Thank you. Long life for stack overflow community! – Roberto Conte Rosito Oct 01 '16 at 08:17
  • `{"link":"https:\/\/www.facebook.com\/app_scoped_user_id\/YXNpZADpBWEdrUlJiUzc0SWFWZATI4SEVJUmJHTTJQVHU2M3owcTJLOHh5MnJYOTI0LWdMT3VFUC1veXNWdXBhM3o3RzdkQmV4cjNfTC1nSkdheGFhV19pWWU5T1ZAWSzlkN0NBTUl4NVZAKTE9oRjlFbjdObU5i\/","id":"1686741234967769"}1` I have this html coming from facebook, I tried converting that into JSON but its not working.. I did like this.. `$request = json_encode($json, JSON_HEX_QUOT | JSON_HEX_TAG);` Please help – Salman Riyaz Jul 05 '18 at 09:09
7

How about convert all the potential problem characters instead of just what fixes the problem in this circumstance:

die(json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE));

http://php.net/manual/en/function.json-encode.php

http://php.net/manual/en/json.constants.php

Andrew
  • 13,934
  • 8
  • 78
  • 93
3

Some stuff to try:

ajaxForm supports dataType argument, if you expect a JSON coming from the server, use dataType: json like so

$("#typeForm").ajaxForm({
    success : function(html){
       // html here is already automatically a json object
       alert(html.prompt);
    },
    dataType: 'json'
}).submit();

Could you post the full service.php? OR try the following:

exit(json_encode(array('file_name' => $data['upload_data']['file_name'], 'prompt' => $str)));

-- EDIT --

Not sure why json_encode returns such weird string :s, is the json_encode a standard php library or an external library? I'm asking this because some servers don't have json_encode in their php installation... I tested on my local and using php internal json_encode and it works fine:

<?php
$str = "<div style='position:relative'><img src='/assets/ui/success.png' /><span style='position:relative;top:-15px;'>Nachricht empfangen!</span></div>";
echo json_encode(array('prompt' => $str));

// output
//{"prompt":"<div style='position:relative'><img src='\/assets\/ui\/success.png' \/><span style='position:relative;top:-15px;'>Nachricht empfangen!<\/span><\/div>"}
Andreas Wong
  • 55,398
  • 19
  • 100
  • 120
  • Thanks for this, but no it doesn't work. If I did this, then it won't alert at all. – planet x Mar 19 '12 at 03:36
  • Do you have a test page on this? Easier if I could go through and test directly – Andreas Wong Mar 19 '12 at 03:37
  • and yes it won't alert as dataType json would expect a valid json string, in which case "HELLO WORLD" isn't a valid json – Andreas Wong Mar 19 '12 at 03:38
  • thanks, but none i don't have a test page for this. it's set on my local. I guess this concerns a malformed JSON because if I var_dump the json_encode it looks like a well-malformed JSON. – planet x Mar 19 '12 at 03:44
  • If you are using chrome browser, press F12 and look on the bottom right corner, if you see something like `(x) 1`, it might tell you. json_encode should properly escape your HTML, so don't worry too much about that http://stackoverflow.com/questions/9492916/putting-html-in-json – Andreas Wong Mar 19 '12 at 03:45
  • edited my answer... it seems your service.php has extra markup towards the end of the script – Andreas Wong Mar 19 '12 at 03:59
3

If you cannot find a better solution for this you can encode the value to base64 encoding:

$data = array('upload_data' => $this->upload->data());
$str = base64_encode("<div style='position:relative'><img src='/assets/ui/success.png' /><span style='position:relative;top:-15px;'>Nachricht empfangen!</span></div>");
echo json_encode(array('file_name' => $data['upload_data']['file_name'], 'prompt' => $str));

and in the client decode it, IMO this is more safer this is also more applicable if you're processing characters from different languages.

ALSO:

to sure that no other characters will be added on the json string call exit; writer after you print it.

jerjer
  • 8,482
  • 27
  • 36
  • for chrome or mozilla you can use atob() or btoa() – jerjer Mar 19 '12 at 05:15
  • for other browsers u can use this js library http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html or this http://stackoverflow.com/questions/246801/how-can-you-encode-to-base64-using-javascript – jerjer Mar 19 '12 at 05:16
  • 2
    this is good idea, base64 encode on php side and base64 decode on js side. – Wasim A. Mar 23 '18 at 07:33
  • 1
    I really prefer this approach because you don't have to mess with any json_encode flags! – Rick Dec 29 '20 at 19:18
0

You should call only prompt object of your array not all! like below:

$("#typeForm").ajaxForm({
    success : function(html){
        var obj = $.parseJSON(html);
        alert(obj.prompt);
}).submit(); 
0

JSON doesn't play well with string output that comes out of magic method __toString() - it nearly impossible to json_encode() anything that even remotely touched something like this.

<?php
/**
 * DEBUGGING NIGHTMARE
 * SO MUCH FUN, 10/10,
 */
class Nightmare {
  protected $str;
  public function __construct($str) {
    $this->str = $str;
  }
  public function __toString() {
    return $this->str;
  }
}

$test = new Nightmare('Hello Friends.');
echo $test;
> Hello Friends.

// cooool, so let's JSON the hell out of it, EASY

echo json_encode(['our_hello' => $test]);
// This what you expect to get, right?
> {"our_hello":"Hello Friends."}

// HAHA NO!!!
// THIS IS WHAT YOU GET:
> {"our_hello":{}}


// and this is why is that:

var_dump($test);
object(Nightmare)#1 (1) {
  ["str":protected]=>
  string(14) "Hello Friends."
}

print_r($test);
Nightmare Object
(
    [str:protected] => Hello Friends.
)
Adriaan
  • 15,941
  • 7
  • 35
  • 67
  • 1
    Please keep in mind that Stack Overflow strives to be a professional knowledge base. Jokes and inappropriate language have no place here – Adriaan Jan 07 '20 at 11:21
  • Thank you for demonstrating in a humorous way the problem you encountered. Keep up the good work! – E.Bradford Jan 30 '21 at 00:11
0

It looks like you need to escape your quotes server-side. Since they are in there, it seems to be creating an invalid JSON string.

davehale23
  • 4,322
  • 2
  • 24
  • 39
0
string(214) "{"file_name":"cde595988d386529909ce5a8fe3a6d6f.png","prompt":"<div style="position:relative;"><img src="\/assets\/ui\/success.png" \=""><span style="position:relative;top:-15px;">Nachricht empfangen!&lt;\/span&gt;&lt;\/div&gt;"}"
</span></div>

This seems to be broken because there's no quote escaping. When an unescaped " is found, it breaks the JSON structure you expect. Escaped " should be \", single quotes with \' and so on.

AlfredoVR
  • 3,591
  • 2
  • 23
  • 33