DEMYSTIFYING JSON (for myself)
I'm doing this post because the term 'JSON' has continued to appear here and there within blog posts, conference sessions, articles, and emails that I consume as part of my professional growth regimen. Despite the fact that the term is so very often mentioned casually as if everybody has known about it since Kindergarten, the greater part of my understanding of JSON is barren except for the few clues I have managed to glean through context. So, I decided to take the time to get to know JSON a little more intimately, and learned some interesting things.
WHAT I THOUGHT IT WAS
Based solely on the info I managed to gather from "between the lines", I knew that JSON stood for JavaScript Object Notation, and that it was an alternative to XML when dealing with the results of Ajax calls. Knowing that much, I could deduce that it was basically "data in a string". But what it looked like, how to handle it, and why I would want to do it were still questions in my mind.
WHAT I FOUND IT TO BE
JSON is indeed a string representation of simple or complex data, just as is XML, only without the tags AND without the need to treat that string as a document type in order to transverse it elegantly. JSON contains two indicators: curly braces to indicate that a structure follows, and square brackets to indicate an array. Here's a structure written in JSON: {key1:"val1",key2:"val2",key3:"val3"} and a one dimensional array: ["val1","val2","val3"]. You can nest these types within one another, too; for example, the value of a structure key could be an array, and would be written as this: {key1:["val1","val2","val3"],key2:"val2"}. Pretty cool, eh?
Now, how to get data back and forth between JSON and raw CF types. It's a no-brainer using a tag made available as an open source project on RIA Forge by Andrew Powell: CFJSON . I downloaded it and was using it in less than two minutes on a test template. Very simple, very easy.
All of this good information led me to pose more questions, which I went on to get answers to.
Following are the results of me finding out the answers to those questions.
THE EXPERIMENT
Working with a 500 row recordset, each row containing 52 fields of mixed data types, including some sql text, convert it to both JSON and XML and record the results of the time it took and the resulting string length. Do this in both a local template/cfc environment AND over the wire via a web service. I used CFJSON as the JSON converter, and Ray Camden's XML.cfc as the XML converter.
THE RESULTS
The string size was consistent, as expected. JSON produced a string that was 57% smaller than the same data represented as XML. Even so, the actual difference in the time it takes to send the larger string doesn't even come close to compensating for the additional time it took to produce the shorter JSON string. It took 1,370% LONGER to produce the JSON string than it did the XML string. Wow, at this point it's almost a no-brainer that I would NOT want to use JSON for much if anything. But this huge difference got me to thinking: What was so vastly different about the way the XML was being produced and the way the JSON was being produced? So I dug into the CFCs to find out.
THE DIFFERENCE
Both CFC methods make use of lots and lots of looping and string concatenation. The only glaring difference was in the way this was done. XML.CFC leverages the Java.lang.stringbuffer object and CFJSON uses straight CF string manipulation. So, I altered the portion of the method in CFJSON.CFC that converts queries to utilize the java.lang.stringbuffer object as well. The results were VERY favorable! check out these time tests after I made the switch:
Wow. The conversion to JSON now runs neck in neck with the XML conversion, simply by leveraging the stringbuffer object. Sweeeeet.
Okay, now that I know that JSON data strings are significantly smaller, just as fast to create, how about manipulation? How painful is that? To find out I decided I was going to use my JSON data in a javascript function. I scaled down the size of the data set to only five records and a handful of fields for this test. Check out how simple it was to 'dump' my data into javascript and to access it afterwards:
CONCLUSION
I have come to no solid conclusion as of yet, but I must say that I'm leaning heavily towards JSON in lieu of XML. It's got a smaller footprint all the way around, has the ability to capture complex nesting, and is really straightforward to navigate using Javascript. Additionally, the same way CFJSON can encode complex data, it also DECODES it on the receiving end, turning it back into something that CF recognizes.
Oh, and I think I'm going to email the CFJSON guys and let them know about the significant performance improvement I got when switching to stringbuffer. They may have already experimented in this arena, but just in case, I'll let them know.
That's it for my personal "JSON Demystification". :)
Doug out.
P.S. If you would like to see an actual JSON representation of my five record query, here it is:
WHAT I THOUGHT IT WAS
Based solely on the info I managed to gather from "between the lines", I knew that JSON stood for JavaScript Object Notation, and that it was an alternative to XML when dealing with the results of Ajax calls. Knowing that much, I could deduce that it was basically "data in a string". But what it looked like, how to handle it, and why I would want to do it were still questions in my mind.
WHAT I FOUND IT TO BE
JSON is indeed a string representation of simple or complex data, just as is XML, only without the tags AND without the need to treat that string as a document type in order to transverse it elegantly. JSON contains two indicators: curly braces to indicate that a structure follows, and square brackets to indicate an array. Here's a structure written in JSON: {key1:"val1",key2:"val2",key3:"val3"} and a one dimensional array: ["val1","val2","val3"]. You can nest these types within one another, too; for example, the value of a structure key could be an array, and would be written as this: {key1:["val1","val2","val3"],key2:"val2"}. Pretty cool, eh?
Now, how to get data back and forth between JSON and raw CF types. It's a no-brainer using a tag made available as an open source project on RIA Forge by Andrew Powell: CFJSON . I downloaded it and was using it in less than two minutes on a test template. Very simple, very easy.
All of this good information led me to pose more questions, which I went on to get answers to.
- Were there any performance advantages of using JSON over XML?
- Was there significant differences in the length of the string produced by a JSON conversion as opposed to an XML conversion (significant in the realm of web services where that string will have to be sent over the wire)?
- Were there any compelling reasons to adopt JSON in leiu of XML or WDDX?
Following are the results of me finding out the answers to those questions.
THE EXPERIMENT
Working with a 500 row recordset, each row containing 52 fields of mixed data types, including some sql text, convert it to both JSON and XML and record the results of the time it took and the resulting string length. Do this in both a local template/cfc environment AND over the wire via a web service. I used CFJSON as the JSON converter, and Ray Camden's XML.cfc as the XML converter.
THE RESULTS
| LOCAL TESTS | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
||||||||||||||||||||||||||||||||||||
| WEB SERVICE TESTS | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
||||||||||||||||||||||||||||||||||||
The string size was consistent, as expected. JSON produced a string that was 57% smaller than the same data represented as XML. Even so, the actual difference in the time it takes to send the larger string doesn't even come close to compensating for the additional time it took to produce the shorter JSON string. It took 1,370% LONGER to produce the JSON string than it did the XML string. Wow, at this point it's almost a no-brainer that I would NOT want to use JSON for much if anything. But this huge difference got me to thinking: What was so vastly different about the way the XML was being produced and the way the JSON was being produced? So I dug into the CFCs to find out.
THE DIFFERENCE
Both CFC methods make use of lots and lots of looping and string concatenation. The only glaring difference was in the way this was done. XML.CFC leverages the Java.lang.stringbuffer object and CFJSON uses straight CF string manipulation. So, I altered the portion of the method in CFJSON.CFC that converts queries to utilize the java.lang.stringbuffer object as well. The results were VERY favorable! check out these time tests after I made the switch:
| CFJSON.CFC TESTS AFTER STRINGBUFFER CONVERSION | ||
|---|---|---|
| TEST | LOCAL TIME(ms) | WEB SERVICE TIME(ms) |
| 1 | 2156 | 4437 |
| 2 | 2125 | 3843 |
| 3 | 2031 | 4022 |
Wow. The conversion to JSON now runs neck in neck with the XML conversion, simply by leveraging the stringbuffer object. Sweeeeet.
Okay, now that I know that JSON data strings are significantly smaller, just as fast to create, how about manipulation? How painful is that? To find out I decided I was going to use my JSON data in a javascript function. I scaled down the size of the data set to only five records and a handful of fields for this test. Check out how simple it was to 'dump' my data into javascript and to access it afterwards:
<script>
function showMeSomeJSON(){
var objQuery = <CFOUTPUT>#jsondata#</CFOUTPUT>;
var i = 0;
for(i=0;i<objQuery.recordcount;++i){
alert(objQuery.data.due_date[i]);
}
}
</script>
function showMeSomeJSON(){
var objQuery = <CFOUTPUT>#jsondata#</CFOUTPUT>;
var i = 0;
for(i=0;i<objQuery.recordcount;++i){
alert(objQuery.data.due_date[i]);
}
}
</script>
CONCLUSION
I have come to no solid conclusion as of yet, but I must say that I'm leaning heavily towards JSON in lieu of XML. It's got a smaller footprint all the way around, has the ability to capture complex nesting, and is really straightforward to navigate using Javascript. Additionally, the same way CFJSON can encode complex data, it also DECODES it on the receiving end, turning it back into something that CF recognizes.
Oh, and I think I'm going to email the CFJSON guys and let them know about the significant performance improvement I got when switching to stringbuffer. They may have already experimented in this arena, but just in case, I'll let them know.
That's it for my personal "JSON Demystification". :)
Doug out.
P.S. If you would like to see an actual JSON representation of my five record query, here it is:
{"recordcount":5,"columnlist":"complete,date_desired,dept,details,developer,due_date,est_hours","data":{"complete":["100%","100%","0%","100%","0%"],"date_desired":["Less Than 2 weeks","Less Than 1 week","More Than 2 weeks","Less Than 1 week","Less Than 1 week"],"dept":["Eligibility","Marketing","Benplan_com","Repricing","EDI"],"details":["1. For rehires, if a rehire date is present on the file and the rehire date is greater than the date of hire, then I need to use it.\r\n\r\n2. Cobra reason - make sure the term reason for a benefit is being put on the AE2 file. This is tied in with Scott\'s work.\r\n\r\n3. Some dependents have termed benefits but no effective dates, also no effective date for the employee. I need to find out where these are coming from.\r\n\r\n4. Terms need to be removed from the file 60 days after the employment term date. This will actually be added to the TSS AE2 file as well.","Dave Lawson, SWI, would like for us to send him the annual report we created for him that gives him EE and Dependent data for Group #s 90947 and 90947P.","- We will send?? or receive daily RX claims\/deductible file updates to one or two PBM\'s--Innoviant for sure and maybe Catalyst.\r\n"," 1) Show correct network for each group. 2) Change elapsed days to start counting on the day the claim was sent out. ","Correct the SSN validation on inbound EDI returned repriced claims. "],"developer":["Dan Crouch","Kelly Young","Gemma Anthony","Kelly Billen","Kelly Billen"],"due_date":["09\/09\/2004","8\/19\/04","NA","08\/30\/2004","08\/13\/2004"],"est_hours":["",1,400,1,1 ]}}
Subscription Options
You are not logged in, so your subscription status for this entry is unknown. You can login or register here.
Re: DEMYSTIFYING JSON (for myself)
I'm the maintainer of CFJSON, just wanted to let you know that the version on the CFJSON site is much more up-to-date ( http://www.epiphantastic.com/cfjson ). But it also doesn't use the java stringBuffer, which Ray Camden recently pointed out, and it's on my to-do list. I guess if you've taken care of it already it would come in handy. Great tests, btw. I bet that with JSON becoming a standard in CF 8 it will perform significantly faster since the functions are native. CFJSON will still be useful for folks on CF 7 and less.
Posted by Thomas Messier on July 5, 2007 at 7:06 PM
Re: DEMYSTIFYING JSON (for myself)
I'd be interested in seeing you run these identical tests on CF8. I believe that HostMySite has free CF8 beta accounts for a limited time. You could try running it there, or ask someone that has 8 (Ray maybe) to run them for you. Thanks for doing the legwork.
Posted by Andy Matthews on July 5, 2007 at 10:12 PM
Re: DEMYSTIFYING JSON (for myself)
Please look to Thomas's implementation. He maintains CFJSON now. Although, we'll all be obsolete when CF8 arrives!
Posted by Andrew Powell on July 6, 2007 at 7:25 AM
Re: DEMYSTIFYING JSON (for myself)
Nice work, Doug! Thanks for the informative post.
Posted by Hal Helms on August 14, 2007 at 1:23 AM