jmoiron/jsonq — pull request #2 by CheRuisiBesares (2013-12-29 18:48:40+00:00)
Title: Adding some type array functionality.

Hey I use this library a lot in my personal projects. One of the things that I find my self doing over and over again is retrieving an array and then walking through it in order to change the type from say []interface{} to []string. In order to capitalize on some of the nice safeties you have built in for the conversions I find myself making ugly routines that essentially use jsonq to find the array, get its length and then iterate over the length using jsonq to return each of the indexes. There are obviously several ways of doing this however I think that it would be nice to have some of these routines built in. I realize that JSON arrays don't have to contain objects of only one type but when working with exchanges between multiple well typed go apis it might make more sense to assume arrays will contain like types.

For example using the available api we might do something like this:
```go
//function that we want to call after unpacking the json
func DoSomething(strings []strings) {}

func main() {
//json however you get it
const json = `{
"collections": {
"strings": ["hello", "strings"],
}
}`

data := map[string]interface{}{}
dec := json.NewDecoder(strings.NewReader(json))
dec.Decode(&data)
q := NewQuery(data)
//get the array
a, err := q.Array("collections", "strings")
if err != nil {
//handle error
}
//begin conversion
stringArray := make([]string, len(a))
for i := range a {
//conversion of choice here but you lose what this lib gives you with floats for example
s, err := q.String("collections", "strings", 0)
if err != nil {
//handle error
}
stringArray[i] = s
}
//do what we actually wanted to do
DoSomething(stringArray)
}
```

I have extended the API with the following functions
```go
//ArrayOfStrings extracts an array of strings from some json
func (j *JsonQuery) ArrayOfStrings(s ...string) ([]string, error)
//ArrayOfInts extracts an array of ints from some json
func (j *JsonQuery) ArrayOfInts(s ...string) ([]int, error)
//ArrayOfFloats extracts an array of float64s from some json
func (j *JsonQuery) ArrayOfFloats(s ...string) ([]float64, error)
//ArrayOfBools extracts an array of bools from some json
func (j *JsonQuery) ArrayOfBools(s ...string) ([]bool, error)
//ArrayOfObjects extracts an array of map[string]interface{} (objects) from some json
func (j *JsonQuery) ArrayOfObjects(s ...string) ([]map[string]interface{}, error)
//ArrayOfArrays extracts an array of []interface{} (arrays) from some json
func (j *JsonQuery) ArrayOfArrays(s ...string) ([][]interface{}, error)
//Matrix2D is an alias for ArrayOfArrays
func (j *JsonQuery) Matrix2D(s ...string) ([][]interface{}, error)
```

This would allow us to rewrite the above example like this:
```go
func DoSomething(strings []strings) {}

func main() {
const json = `{
"collections": {
"strings": ["hello", "strings"],
}
}`

data := map[string]interface{}{}
dec := json.NewDecoder(strings.NewReader(json))
dec.Decode(&data)
q := NewQuery(data)
stringArray, err := q.ArrayOfStrings("collections", "strings")
if err != nil {
//handle error
}
DoSomething(stringArray)
}
```

Which is a little more manageable and also drops some of the recursive calls while preserving the existing type conversion routines.

Let me know what you think about these modifications. I followed your lead with the testing suite. If you want to see more rigorous testing or want to split up the main jsonq file let me know. Anyway thanks for the great library.