Leer ficheros JSON en Golang

Ahora estoy usando Go para mis programas y necesitaba leer algunos ficheros JSON. ¿Y eso como se hace? Bueno, afortunadamente Golang tiene una librería estándar muy completa que nos simplifica las cosas. Aquí encuentras como lo hice.

Este es mi fichero JSON llamado 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."
  }
]

Ahora seguimos con las buenas practicas del TDD (test-driven development), así que como primera cosa escribimos una función de test en 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)
    }
}

por supuesto, si ejecutamos el test ahora nos fallará porqué todavía no hemos escrito la función getTentacles()

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

y este es el programa main en 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())
    }
}

Ahora el test pasa sin problemas

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

y esto es el output del programa

$ 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."}

Como puedes ver, he usado una struct para guardar los datos JSON, si necesitas convertir datos JSON en estructuras de Go (struct) te aconsejo de mirar la pagina web JSON-to-Go.

Danilo