Wednesday, May 20, 2009

Java/JSON numeric data types

Working on a Java-based project for Grooveshark, I ran into an issue with the Java JSON library's numeric datatype parsing. My data source is a pretty run-of-the-mill MySQL database and, as you may know, if you have a table with an INT column (very common for primary key ID fields), Java imports those values as Longs. Now, my code is basically taking data from MySQL, serializing it into JSON text and storing it in memcached for later retrieval. The problem came about as follows: I would load the JSON string from memcached (in this case a list of numbers from an INT UNSIGNED PRIMARY KEY column), deserialize it, and convert it from a JSON Array to a Java List<Long>. At the same time, I had another List<Long> of values coming in from the database, and I performed a simple check to see if one list contained the other as a subset. Say the JSON-based list was called jsonIDs and the list from the DB dbIDs -- I called jsonIDs.containsAll(dbIDs). In this particular case, both lists had only one element and by logging them to stdout, I could *see* that they contained the same numerical value. Yet despite my pleas and screaming, jsonIDs.containsAll(dbIDs) returned false. Infuriating! So finally, I wound up writing my own nested for loops to do the comparisons by hand, and sure enough, when I did the comparison on individual elements pulled from the respective lists, I got an exception --
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
Apparently, my List<Long> was nothing of the sort. I thought and thought about where my objects were actually coming from. The DB IDs were clearly coming straight from the database and there couldn't be an issue there. It had to be the JSON-based list. So I downloaded the source code from json.org and dug around. Sure enough, the JSONTokener class, responsible for parsing JSON text into a Java object was the source of the problem. In parsing what it believes to be numeric text, it goes through a series of checks to determine the type of number -- hex, octal, double, and finally long. Unfortunately, when determined to be a whole number and despite being parsed as a long, the JSONTokener makes a final check to see if precision is lost by casting to an Integer. If not, the value is cast to an Integer and returned, and this was the source of my problem. So I pulled the json.org source code into my project and made an easy one-line fix to prevent this cast altogether. Now my (hacked) JSON code will return a long no matter what the (whole-number) value, which may not be ideal in general (hence the original behavior) but does the trick for me. All the numeric values I'm serializing are going to be longs anyway. What I still don't get is why, when loading an Integer into a List<Long>, the object is allowed to keep its Integer type. Shouldn't this object be cast before it can be added to the List? I'm stumped on this one, but hey, my code is working again so I'm movin' on. Any ideas?

Saturday, March 15, 2008

Neat del.icio.us tip

I found a cool new way to use del.icio.us! I've had an account over at del.icio.us for probably a year and while I (somewhat) frequently tag things, I rarely use this service to get to web sites. I'm much more likely to use my google toolbar. However it occurred to me yesterday that 95% of the time, when I open a fresh browser window, there are maybe 5 places I'm likely to be headed. Traditionally, I've had my browser home page set to gmail.com and this choice is pretty arbitrary - although it is one of the 5 places I'm usually headed to when I hit my browser icon.

So here's the tip:
I created a special tag ("favorite" as it were) and tagged each of these special sometimes-homepages with this special tag. Then I set my browser homepage to http://del.icio.us/cgs1019/favorite. Now when I open my browser, I've got my hand-picked set of likely destinations.

If you don't have a del.icio.us account, you should! It's a great way to keep track of all the sites you're interested in without having a Bookmarks menu that goes down to the floor. Also, it's a great way to utilize this awesome tip which I went to so much trouble to share.
So check it out!

Monday, March 10, 2008

Hello World

This will be my obligatory, self-referential, initial meta-post here on GNU Guy. Those to come will be wrought with tales from the trenches of a little internet startup in Gainesville, and anything else I feel compelled to share. I am an otherwise utterly inexperienced and unqualified software engineer. My degree is in mathematics and my interest in software has always been recreational, however through a seemingly unlikely sequence of events, I can now be found quite thoroughly embedded in the zany world of open source software and web development. Sometimes I sound like I really know what I'm talking about (I do!) and sometimes I sound like I really have no idea what I'm talking about (I don't!). It's fun; I hope to recreate a little of it here.