Read JSON files in Golang

I'm using Go language now and I needed to read JSON files. How do I do that? Well, thankfully Golang has an extensive standard library which make it easy. Here's how I did it.

This is my JSON file called tentacles.json

[
  {
    "name": "Purple Tentacle",
    "description": "A mutant monster and lab assistant created by mad scientist Dr. Fred Edison."
  },
  {
    "name": "Green Tentacle",
    "description": "Harmless and friendly brother of Purple Tentacle."
  },
  {
    "name": "Bernard Bernoulli",
    "description": "Green Tentacle's friend, he's a nerd with glasses."
  }
]

Let's follow TDD (test-driven development) best practice, so first thing is to write a function test in json_test.go

package main

import "testing"

// TestReadJSON testing read from JSON file
func TestReadJSON(t *testing.T) {
    tentacles := getTentacles()
    tentacle := tentacles[2]
    expectedName := "Bernard Bernoulli"
    expectedDescription := "Green Tentacle's friend, he's a nerd with glasses."
    if expectedName != tentacle.Name {
        t.Errorf("Tentacle.name == %q, want %q",
            tentacle.Name, expectedName)
    }
    if expectedDescription != tentacle.Description {
        t.Errorf("Tentacle.description == %q, want %q",
            tentacle.Description, expectedDescription)
    }
}

of course if we run this test it will fails as we didn't write getTentacles() function yet

$ go test -v
# dd-golang/json
./json_test.go:7: undefined: getTentacles
FAIL    dd-golang/json [build failed]

and this is main program json.go

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
)

// Tentacle a character from Day of Tentacles
type Tentacle struct {
    Name        string `json:"name"`
    Description string `json:"description"`
}

func (t Tentacle) toString() string {
    bytes, err := json.Marshal(t)
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }
    return string(bytes)
}

func getTentacles() []Tentacle {
    tentacles := make([]Tentacle, 3)
    raw, err := ioutil.ReadFile("./tentacles.json")
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }
    json.Unmarshal(raw, &tentacles)
    return tentacles
}

func main() {
    tentacles := getTentacles()
    fmt.Println(tentacles)
    for _, te := range tentacles {
        fmt.Println(te.toString())
    }
}

Now test is passed

$ go test -v
=== RUN   TestReadJSON
--- PASS: TestReadJSON (0.00s)
PASS
ok      dd-golang/json  0.002s

and here the program's output

$ go run json.go
[{Purple Tentacle A mutant monster and lab assistant created by mad scientist Dr. Fred Edison.} {Green Tentacle Harmless and friendly brother of Purple Tentacle.} {Bernard Bernoulli Green Tentacle's friend, he's a nerd with glasses.}]
{"name":"Purple Tentacle","description":"A mutant monster and lab assistant created by mad scientist Dr. Fred Edison."}
{"name":"Green Tentacle","description":"Harmless and friendly brother of Purple Tentacle."}
{"name":"Bernard Bernoulli","description":"Green Tentacle's friend, he's a nerd with glasses."}

As you can see, I used a struct to store JSON data, if you need to convert JSON data to Go struct, have a look to JSON-to-Go page.

Danilo