Sunday, December 9, 2012

Creating a Go Library: Part 1

Intro

This tutorial will follow my progress working on a library that would handle working with dynamic JSON data. Go is a great language for decoding JSON when the data layout is fixed, but since Go is a static language, dealing with JSON that is dynamic can be less intuitive than when working with dynamic languages like PHP, Ruby, or Python.  This tutorial assumes that you have some working knowledge of Go.  If you have no prior knowledge of Go, go here and here.

<rant>
I think Go is lacking in regards to the amount of intermediate and advanced examples that show how Go works solving actual problems instead of a "10000 foot view"of Go.  I have great respect for the Go team and in particular, I think Andrew Gerrand is doing a great job of representing Go accross the globe, but if I see one more video of Andrew demoing chat roulette, I will commit Seppuku
</rant>

Taking a whack at it

This is the sample JSON data from the Github API I am working with.  And here is a sample JSON record.

Looking at the events data, I found that the payload object is different depending on the "type" of event.  Immediately, I wanted to go back to my PHP roots and use $event = json_decode($source) and this problem would be solved, but the following example uses the most basic Go code.



The problem with this is you can only access top level data items.  For instance, I can access the payload by using m["type"] but trying to get m["payload"]["description"] will not compile because an interface does not have any indexes.  So what can we do to clean this up?  I created a couple of structs and some basic functions to help me decode the JSON.  I wanted a JSONCollection struct which contained the entire document and JSONObject which would be the struct used to read the results.


This still has the same limitation as before.  I can use "Get" to find a top level attribute, but If I want a nested attribute, I have to type cast the interface to a map again and then grab the description out of that map.  I need to come up with a better solution. The goal is to have syntax like the following.





This will give us a cleaner syntax to get at nested variables. So let's fix the code to allow this.


This gives a start to our library.  Now we can retrieve strings of data (and nested data) with a minimal amount of Go code.  Here is a an example as to how we would use this library.


Current Limitations

The library uses only strings, so if you have an integer or float, those values will have trouble converting to strings (I will fix this in a later blog post).  You will have trouble traversing nested slices as that this will cause an error.  Currently the example is read-only, as that was all that was initially needed.

Coming Up on Personal Ramblings

I want to make this a feature complete library, so here is a list of things that I want to add to this library.  
  • Get JSON Object by Position
  • Get JSON Objects by using limit/offset
  • Filter JSON Results
  • Handling different variable types
  • Creating Tests
  • Creating a better Iterator
  • Using Godoc
  • Using GoFmt
If you feel anything is missing, feel free to comment below.  When completed I will be releasing the source for this library on Github.