CodeIgniter Forums
Using JSON in data attributes with JS - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: General (https://forum.codeigniter.com/forum-1.html)
+--- Forum: Lounge (https://forum.codeigniter.com/forum-3.html)
+--- Thread: Using JSON in data attributes with JS (/thread-69398.html)



Using JSON in data attributes with JS - skunkbad - 11-14-2017

I don't know if it's considered bad practice, or if it's the way everyone does it, but I find myself inserting JSON data into HTML element attributes all the time. So, for instance:

PHP Code:
foreach( $query->result_array() as $row )
    
$arr[] = (object) array_map'html_escape'$row );

$json json_encode$arr );

$json_string str_replace([
    
'"',
    
''',
    
'& #039;' // space here for codeigniter forum
], [
    
'\u0022',
    
'\u0027',
    
'\u0027'
], $json ); 

Now I know that json_encode has options like JSON_HEX_APOS and JSON_HEX_QUOT, but I also want to use html_escape() which is why I'm using str_replace the way I am. This allows me to do this:


PHP Code:
echo '<div data-json=\'' $json_string '\'>'

Then later in my json I can use JSON.parse() on the contents of that data-json attribute.

What are your thoughts here? Is there a better way?


RE: Using JSON in data attributes with JS - ivantcholakov - 11-14-2017

For views I use the Twig parser and here is a test on how I would do this:

Code:
<div id="test_element" data-json="{{ '{ "value_1": "A test string value.", "value_2": 2 }'|e('html_attr') }}"></div>

<script>

    $(function() {

        var data_json = $('#test_element').attr('data-json');
        alert(data_json);

        var data = JSON.parse(data_json);
        alert(data.value_1);
        alert(data.value_2);
    });

</script>

This works, and the produced HTML code looks like this:

Code:
<div id="test_element" data-json="&#x7B;&#x20;&quot;value_1&quot;&#x3A;&#x20;&quot;A&#x20;test&#x20;string&#x20;value.&quot;,&#x20;&quot;value_2&quot;&#x3A;&#x20;2&#x20;&#x7D;"></div>

<script>

    $(function() {

        var data_json = $('#test_element').attr('data-json');
        alert(data_json);

        var data = JSON.parse(data_json);
        alert(data.value_1);
        alert(data.value_2);
    });

</script>

For PHP views this example would be:

Code:
<div id="test_element" data-json="<?php echo html_attr_escape('{ "value_1": "A test string value.", "value_2": 2 }'); ?>"></div>

<script>

    $(function() {

        var data_json = $('#test_element').attr('data-json');
        alert(data_json);

        var data = JSON.parse(data_json);
        alert(data.value_1);
        alert(data.value_2);
    });

</script>

The helper function html_attr_escape() is introduced by me, it calls the Twig's escaper to do the job.
https://github.com/ivantcholakov/starter-public-edition-4/blob/v4.3.24/platform/common/core/Common.php#L283

If you don't need Twig to be installed in your project, you can implement html_attr_escape() by using the escaper form Zend. https://github.com/zendframework/zend-escaper/blob/master/src/Escaper.php#L155 The escapers of Twig seem to be ported from Zend. I can see that CodeIgniter 4 would use the Zend Escaper, you can back-port this function: https://github.com/bcit-ci/CodeIgniter4/blob/develop/system/Common.php#L219 :

Code:
<div id="test_element" data-json="<?php echo esc('{ "value_1": "A test string value.", "value_2": 2 }', 'attr'); ?>"></div>

In conclusion, you should find a way to escape the data html attribute as html attribute, it does not matter whether it would contain json data or something else. I think, the trivial way would be the best here, everyone would understand it without getting bored or tired.


RE: Using JSON in data attributes with JS - skunkbad - 11-14-2017

ivantcholakov, that Escaper class is very thorough. My only concern is that when testing, it took a 41 character string of json and turned it into 127 characters.

So this:


PHP Code:
$escaper = new Escaper('utf-8');
$str $escaper->escapeHtmlAttr(json_encode([
 
   'yodels' => 'Brian\'s',
 
   'lemons' => '"Lovely"'
]));
echo 
$str

Became this:


Code:
&#x7B;&quot;yodels&quot;&#x3A;&quot;Brian&#x27;s&quot;,&quot;lemons&quot;&#x3A;&quot;&#x5C;&quot;Lovely&#x5C;&quot;&quot;&#x7D;

If I've got a lot of json, I guess I might need to put it somewhere besides an attribute.

Thanks for the links. That Escaper class is pretty cool. Definitely useful and easier to use than rolling my own.


RE: Using JSON in data attributes with JS - ivantcholakov - 11-14-2017

Another possible way that I used in the past is using base_64 encoded strings, they could be put as attributes directly. But this is a complication that I don't like, the JavaScript should decode from base_64 first and then to decode the JSON string.


RE: Using JSON in data attributes with JS - skunkbad - 11-15-2017

(11-14-2017, 11:48 PM)ivantcholakov Wrote: Another possible way that I used in the past is using base_64 encoded strings, they could be put as attributes directly. But this is a complication that I don't like, the JavaScript should decode from base_64 first and then to decode the JSON string.

I haven't used that technique, but I saw that it can be done, decoding in JS with atob(). For me I just want something that is easy and foolproof.


RE: Using JSON in data attributes with JS - ivantcholakov - 11-15-2017

About base_64 I used this JavaScript: http://www.webtoolkit.info/javascript-base64.html#.WgxPf3RSxhG , it worked for me. Probably there are other similar ones.

I did not try atob(), I am not sure about it: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem


RE: Using JSON in data attributes with JS - skunkbad - 11-15-2017

(11-15-2017, 08:33 AM)ivantcholakov Wrote: About base_64 I used this JavaScript: http://www.webtoolkit.info/javascript-base64.html#.WgxPf3RSxhG , it worked for me. Probably there are other similar ones.

I did not try atob(), I am not sure about it: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem

 Re the second link, gotta laugh at "Solution #1 – escaping the string before encoding it". That would just make the string even longer.