<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tech Blog &#187; Prototype</title>
	<atom:link href="http://assanka.net/content/tech/tag/prototype/feed/" rel="self" type="application/rss+xml" />
	<link>http://assanka.net/content/tech</link>
	<description>Just another Arb-assk2009003.turmeric.assanka.com Blogs weblog</description>
	<lastBuildDate>Mon, 29 Aug 2011 19:00:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JSON2.js vs Prototype</title>
		<link>http://assanka.net/content/tech/2009/09/02/json2-js-vs-prototype/</link>
		<comments>http://assanka.net/content/tech/2009/09/02/json2-js-vs-prototype/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 16:24:23 +0000</pubDate>
		<dc:creator>Andrew Betts</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Prototype]]></category>

		<guid isPermaLink="false">http://assanka.net/content/tech/?p=5</guid>
		<description><![CDATA[We use Douglas Crockford&#8217;s json2.js frequently in our web apps.  Its stringify method allows JavaScript data structures to be trivially serialised before submission via AJAX to a web service.   It works by descending through the structure, calling the toJSON() method on anything it finds.  It also creates toJSON methods for data [...]]]></description>
			<content:encoded><![CDATA[<p>We use <a title="Douglas Crockford" rel="homepage" href="http://crockford.com/">Douglas Crockford</a>&#8217;s json2.js frequently in our web apps.  Its stringify method allows JavaScript data structures to be trivially serialised before submission via AJAX to a web service.   It works by descending through the structure, calling the <code>toJSON()</code> method on anything it finds.  It also creates <code>toJSON</code> methods for data types that do not already have them, on the basis that future browsers will introduce <code>toJSON()</code> support &#8211; at which point the native implementation can be used because it&#8217;s likely to be a lot faster.</p>
<p>Recently I needed to use this method to serialise some data in a JavaScript library that might be used in &#8216;foreign&#8217; web pages.  My own library was nicely encapsulated, and didn&#8217;t interfere with any other JavaScript that might be running on the page, and it included Douglas Crockford&#8217;s JSON2.js implementation.</p>
<p>But on one of our clients&#8217; sites, it didn&#8217;t work.  I got this:</p>
<pre class="brush: jscript;">
{&quot;key&quot;:&quot;val&quot;,[\{\&quot;key\&quot;:\&quot;val\&quot;\},\{\&quot;key\&quot;:\&quot;val\&quot;\}]}
</pre>
<p>What&#8217;s happened here is that any arrays in my data structure have been stringified twice.  This didn&#8217;t happen in my dev environment.  I narrowed down the differences and realised what was causing this effect.  They&#8217;re using <a href="http://prototypejs.org">Prototype</a>.  We&#8217;re not.</p>
<p>Prototype modifies a number of JavaScript&#8217;s native objects, including the Array object, and&#8230; you guessed it, adds a <code>toJSON()</code> method to it. Unfortunately it does not return what Crockford&#8217;s <a title="JSON" rel="homepage" href="http://json.org/">JSON</a> implementation is expecting.  From the docs for json2:</p>
<blockquote><p>A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized.</p></blockquote>
<p>Prototype&#8217;s <code>toJSON()</code> <em>is</em> serialising.  There don&#8217;t seem to be any sensible solutions to this online, but it&#8217;s actually relatively simple to solve using a replacer function, allowed for in the json2 API:</p>
<pre class="brush: jscript;">
var reqdata = JSON.stringify(req, function(key, value) {
	if (typeof this[key] == 'object' &amp;&amp; Object.prototype.toString.apply(this[key]) === '[object Array]') {
		return this[key];
	} else {
		return value;
	}
});
</pre>
<p>Essentially this says &#8216;for each key in the data structure, if the value is an array, use the raw value, otherwise use the value you gave me&#8217;.  This makes sense when you look at the sequence of steps that stringify() goes through for each key it encounters:</p>
<ol>
<li>If the value has a toJSON() method, call it.</li>
<li>If a replacer function has been given, call it.</li>
<li>If the remaining value is a scalar, return it.</li>
<li>If the remaining value is an object, stringify each member, then concatenate keys and values within braces {key:val,key:val}</li>
<li>If the remaining value is an array, stringify each element, then concatenate values within brackets [val,val,val]</li>
</ol>
<p>So, <code>stringify()</code> has already called Prototype&#8217;s <code>toJSON()</code> method by the time it executes the replacer function, but we can use the replacer function to restore the original value, allowing <code>stringify()</code> to then deal with the array by calling itself recursively.</p>
<p>The result is that we can ensure that even if a <code>toJSON()</code> method does exist on the Array object, its output is ignored, and we then get the JSON string that we wanted.</ol>
]]></content:encoded>
			<wfw:commentRss>http://assanka.net/content/tech/2009/09/02/json2-js-vs-prototype/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

