37

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)));
        }
    }
}
6
  • Your JSON looks like...? Commented Mar 19, 2012 at 3:21
  • by "won't work" do you mean it's throwing errors? Or it doesn't inject the HTML or..? Commented Mar 19, 2012 at 3:22
  • How does it 'not work'? JSON couldn't care less WHAT you're embedding within the string - it can be numbers, it can be text, it can be html. it doesn't matter, as long the JSON syntax rules are honored. Commented Mar 19, 2012 at 3:22
  • guys, see my edited post. sorry for not posting the output. Commented Mar 19, 2012 at 3:24
  • So it alerts... ? Please specify exactly what your problem is and/or the expected behavior... Your question as of now is very vague. Commented Mar 19, 2012 at 3:26

8 Answers 8

113

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);
Sign up to request clarification or add additional context in comments.

4 Comments

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!
{"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
This helped me a lot. One comment: if your response has several components you must parse the whole response first, before splitting the components. Parsing just the html portion didn't work properly.
Important: With json_encode() (without paramaters) you get an object returned that you can access with $obj->attributes. Using the parameters above, it seems that the object is turned into an array, accessible by $obj['attributes'].
11

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

2 Comments

This works great! I was encoding to base64 when I needed to send some html in a JSON response which worked fine until trying to send emojis. Now using the flags above everything works great without needing to encode then decode base64.
This should be top / accepted answer as it solves this problem and any future encoding issues with possible content. Best & most robust solution.
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.

5 Comments

for chrome or mozilla you can use atob() or btoa()
this is good idea, base64 encode on php side and base64 decode on js side.
I really prefer this approach because you don't have to mess with any json_encode flags!
I was using base64 until I had trouble with emojis not rendering, then I switched to json_encode with all the flags and it solved all my problems!
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>"}

6 Comments

Thanks for this, but no it doesn't work. If I did this, then it won't alert at all.
Do you have a test page on this? Easier if I could go through and test directly
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
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.
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 stackoverflow.com/questions/9492916/putting-html-in-json
|
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.

2 Comments

Just what I am suspecting to, but I can't seem to find what's the proper escaping should I do in $str
if you want to manually escape this, you could change to this $str = "<div style=\'position:relative;\'><img src=\'/assets/ui/success.png\' /><span style=\'position:relative;top:-15px;\'>Nachricht empfangen!</span></div>";
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.

Comments

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(); 

Comments

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.
)

2 Comments

Please keep in mind that Stack Overflow strives to be a professional knowledge base. Jokes and inappropriate language have no place here
Thank you for demonstrating in a humorous way the problem you encountered. Keep up the good work!

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.