Serializing the value of empty DOM elements using native JSON in IE8

With native JSON support enabled in IE8, users can now take advantage of the built-in JSON.stringify and JSON.parse methods to serialize and deserialize JScript values to JSON text and vice versa. However, there is a known issue in IE8’s native JSON implementation, wherein if a user tries to read the value of an empty DOM element, and serialize the same using native JSON, the result is not the same as a user would expect while serializing "".

Here is a sample code which demonstrates the problem:

1:var foo = document.createElement("input").value; // foo === ""

2:var bar = ""; // bar === ""

3:

4: JSON.stringify(foo); // retuns '"null"'

5: JSON.stringify(bar); // retuns '""'

Another similar example is when a user serializes the value from an empty input control, as below.

1:var foo = document.getElementById('data').value; // no value provided in the 'data' input control

2: JSON.stringify(foo); // retuns '"null"'

In both the above cases, serialization of foo should have generated '""' instead of '"null"'. This is a bug in the production version of IE8. The problem here is that within the DOM a special encoding is used to represent a missing string value. Even though this special value is different from the encoding of the JScript literal "", throughout the JScript implementation the value is treated as being === to "", except for a specific case in JSON.stringify.

Since this special value only originates from accesses to DOM objects, a workaround would be to explicitly censor them on every DOM access that might return one. For example,

Also, since the difference is only observable via JSON.stringify, another alternative is to use the replacer function to perform the substitution. For example:

1: JSON.stringify(foo, function(k, v) { return v === "" ? "" : v });

2://the above will return '""', not '"null"'

Either of the above workarounds has the disadvantage that additional code must be written each time the value of an InputElement element is accessed or each time JSON.stringify is called. Another possible workaround that avoids this extra coding is to use the IE8 Mutable DOM Prototype features to patch HTMLInputElement.prototype.value such that the undesired value is filtered out every time value is accessed. For example, consider this HMTL file:

In the <head> of this page a test is made to see if the anomalous stringify behavior is observed. If so, HTMLInputElement.prototype.value is modified to correct the problem. Any access to the value property of an Input element within the body of the page, such as the click handler that is shown, will now return the correct "" value.

This explains the anomaly in the IE8 JSON behavior while serializing the value of certain DOM elements and show three different possible workarounds to the problem.

If "this is a bug in the production version of IE8" then why don’t you just roll out an update to IE8 to fix this fullstop rather than giving us all these horrible workarounds..? i can understand the need for the workarounds, but if windows update pushes out a new release of IE8 then within a couple of months, everyone should have the fixed version fullstop..?

I don’t have IE8 installed so I don’t know if this will actually work, (Might give you a permission or other error) but can’t you fix it locally by replacing the reference to the stringify function entirely with a wrapper? Something like:

function fixStringify(){

var _stringify = JSON.stringify;

JSON.stringify = function(o, f){

if (o === "") o = "";

return _stringify(o, f);

}

}

fixStringify();

If the replacement work, all subsequent calls to JSON.stringify should be transparently wrapped. (The fixStringify function is only there to create a private namespace for the old reference.)

@nitro2k01: Yes, such a wrapper will also work. This is similar to the first two workarounds suggested above (but can be applied globally). One small issue in the snippet you provided is that stringify has three parameters instead of two – value, replacer and space.

I’m sure the JScript team would prefer to ship the fix ASAP, but thanks all the same for publishing the issue to your blog and offering workarounds rather than ignoring or pretending it doesn’t exist and leaving it for developers to discover.