Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML string ( ) breaking JSON

I'm collecting some data from my page, storing the data in an array for multiple uses on the page, and sending a copy of the array via AJAX, storing the data in the database on a PHP page.

One piece of data I'm storing in the array is the output of a TinyMCE WYSIWYG editor, so it contains HTML, but have just found this to be a problem - I'll explain:

After entering one line of text in my WYSIWYG editor and I trigger my AJAX event, this is the JSON string displayed in my console and everything worked okay, the database was sent and stored:

{"id":"229","topic":"","title":"","description":"","content":"<p>fgfgfdg.</p>","keywords":""}

If I write two lines of text, this is the JSON string and was successful:

{"id":"229","topic":"","title":"","description":"","content":"<p>fgfgfdg.</p>\n<p>fgfgfdg</p>","keywords":""}

Now, if I write one line of text and press return and not type anything on the second line, I get the following which fails.

{"id":"229","topic":"","title":"","description":"","content":"<p>fgfgfdgdfgdfgdfgdfg.</p>\n<p>&nbsp;</p>","keywords":""}

It seems &nbsp; broke my JSON output somehow. My PHP can't access the decoded array values, as there is no array. print_r(json_decode($json)) returns nothing. Can anybody help?

This is my HTML page with jQuery:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<script>
var post_data = {};

post_data.id = post_id;
post_data.topic = topic;
post_data.title = title;
post_data.description = description;
post_data.content = tinyMCE.activeEditor.getContent();
post_data.keywords = keywords;

post_data = JSON.stringify(post_data);

save_post_request = $.ajax({
    url: 'ajax/save-post.php',
    type: 'POST',
    data: "save_mode="+save_mode+"&post_data="+post_data,
    dataType: 'text',
    cache: false
});
</script>

This is my PHP page:

header('Content-type: application/json; charset=UTF-8');

$post_data = isset($_POST['post_data']) ? $_POST['post_data'] : null;
$post_data_arr = json_decode($post_data, true);
$post_id = $post_data_arr['id'];
$topic = $post_data_arr['topic'];
// others
$content = $post_data_arr['content'];

if (!$post_data_arr['id']) {
    // fails here
    // id is not accessible when the JSON contains <p>&nbsp;</p> in the 'content' item
}

This is what Firebug says:

enter image description here

like image 521
TheCarver Avatar asked Jan 11 '23 12:01

TheCarver


1 Answers

You are placing the JSON into some URL Encoded data, but you are not URL Encoding it.

The & character has special meaning in URL Encoded data (it separates key/value pairs), so this means you are breaking the data.

Use the encodeURIComponent function to properly encode your data before adding it to the string:

data: "save_mode="+encodeURIComponent(save_mode)+"&post_data="+encodeURIComponent(post_data),

However, since you are using jQuery, you shouldn't be constructing your URL Encoded data by hand in the first place. jQuery can do it for you. Pass data an object instead of a string:

data: {
    save_mode: save_mode,
    post_data: post_data
}, 
like image 153
Quentin Avatar answered Jan 16 '23 22:01

Quentin