Search code examples
javascriptjqueryserializationurl-encodinghtml-encode

How can I *HTML*-encode form contents when serializing with jQuery.serialize()?


The jQuery form .serialize() method serializes form contents to a string and automatically URL-encodes the string. My server then reverses this process and URL-decodes the string when deserializing it.

But what I need to be able to do is to HTML-encode the form contents before the form is serialized. In other words, if a user enters HTML into a text input in my form, I want this to be made safe using HTML encoding, then transmitted exactly as described above (using URL-encoding as normal).

Let me illustrate with an example:

Current implementation using .serialize()

  1. User enters My name is <b>Fred</b> into a form input with name Details.
  2. .serialize() serializes this as Details=My+name+is+%3Cb%3EFred%3C%2Fb%3E (URL-encoding)
  3. The server deserializes the string and gets My name is <b>Fred</b> (URL-decoding)

What I want to happen

  1. User enters My name is <b>Fred</b> into a form input with name Details.
  2. This gets HTML-encoded to My name is &lt;b&gt;Fred&lt;/b&gt; (HTML-encoding)
  3. .serialize() serializes this as Details=My+name+is+%26lt%3Bb%26gt%3BFred%26lt%3B%2Fb%26gt%3B (URL-encoding)
  4. The server URL-decodes the string and gets My name is &lt;b&gt;Fred&lt;/b&gt; (URL-decoding only)

I was hoping that .serialize() might take an argument to specify that the form contents should be HTML-encoded, but no such luck. A couple of other possible solutions would be:

  1. Iterate through the form inputs and HTML-encode them "by hand" before calling .serialize(): I'd rather not have to do this as it will make the code messier and less robust.
  2. Modify my server to accept non-HTML-encoded values: for various reasons I won't go into this is problematic and not a practical solution.

Is there a simpler solution?


Solution

  • The solution is to use jQuery's .serializeArray() and apply the HTML-encoding to each element in a loop.

    In other words, I had to change this:

    $.ajax({
        url: form.attr('action'),
        async: false,
        type: 'POST',
        data: form.serialize(),
        success: function (data) {
            //...
        }
    });
    

    to this:

    // HTML-encode form values before submitting
    var data = {};
    $.each(form.serializeArray(), function() {
        data[this.name] = this.value
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
    });
    
    $.ajax({
        url: form.attr('action'),
        async: false,
        type: 'POST',
        data: data,
        success: function (data) {
            //...
        }
    });