JSON

JSON #

// Go ha il supporto builtin per l'encoding e il decoding
// di JSON, con anche la possibilità di convertire verso o
// da tipi builtin e personalizzati.

package main

import "encoding/json"
import "fmt"
import "os"

// Useremo questi due struct per dimostrare l'encoding e
// il decoding di tipi personalizzati.
type Response1 struct {
    Pagina int
    Frutti []string
}
type Response2 struct {
    Pagina int      `json:"pagina"`
    Frutti []string `json:"frutti"`
}

func main() {

    // Come prima cosa vedremo come fare l'encoding di
    // datatype nativi per ottenere stringhe JSON. Ecco
    // degli esempi per dei valori atomici.
    bolB, _ := json.Marshal(true)
    fmt.Println(string(bolB))

    intB, _ := json.Marshal(1)
    fmt.Println(string(intB))

    fltB, _ := json.Marshal(2.34)
    fmt.Println(string(fltB))

    strB, _ := json.Marshal("gopher")
    fmt.Println(string(strB))

    // E ora degli esempi con le slice e le map, che
    // restituiscono degli array e oggetti JSON come ti
    // aspetteresti.
    slcD := []string{"mela", "pesca", "pera"}
    slcB, _ := json.Marshal(slcD)
    fmt.Println(string(slcB))

    mapD := map[string]int{"mela": 5, "lattuga": 7}
    mapB, _ := json.Marshal(mapD)
    fmt.Println(string(mapB))

    // Il package JSON può codificare automaticamente
    // dei data type personalizzati, ad esempio delle
    // struct. Includerà solo i field esportati
    // nell'output codificato e di default userà i nomi
    // dei field per le chiavi JSON.
    res1D := &Response1{
        Pagina: 1,
        Frutti: []string{"mela", "pesca", "pera"}}
    res1B, _ := json.Marshal(res1D)
    fmt.Println(string(res1B))

    // Puoi usare dei _tag_ sulle dichiarazioni dei field
    // di una struct per personalizzare il nome della
    // chiave nel JSON finale. Vedi la dichiarazione di
    // `Response2` sopra per vedere un esempio di questi
    // tag.
    res2D := &Response2{
        Pagina: 1,
        Frutti: []string{"mela", "pesca", "pera"}}
    res2B, _ := json.Marshal(res2D)
    fmt.Println(string(res2B))

    // Ora diamo un'occhiata al decoding di valori JSON
    // in valori builtin di Go. Di seguito un esempio di
    // una struttura di dati generica.
    byt := []byte(`{"num":6.13,"strs":["a","b"]}`)

    // Abbiamo bisogno di definire una variabile dove
    // il package JSON metterà i dati decodificati. Questa
    // `map[string]interface{}` sarà una map di stringhe
    // che puntano a dati con datatype arbitrario.
    var dat map[string]interface{}

    // Qui avviene il vero decoding, dove controlleremo
    // anche se c'è stato un errore.
    if err := json.Unmarshal(byt, &dat); err != nil {
        panic(err)
    }
    fmt.Println(dat)

    // Per poter usare i dati nella mappa decodificata,
    // avremo bisogno di fare un type assertion al loro
    // vero valore. Ad esempio, qui facciamo un type
    // assertion del valore in `num` in un `float64`.
    num := dat["num"].(float64)
    fmt.Println(num)

    // Accedere a dati annidati richiede una serie
    // di type assertion.
    strs := dat["strs"].([]interface{})
    str1 := strs[0].(string)
    fmt.Println(str1)

    // Possiamo anche fare il decode di JSON in data
    // type personalizzati. Questo ha il vantaggio di
    // aggiungere un'ulteriore type-safety ai nostri
    // programmi e elimina la necessità dell'uso dei
    // type assertion quando accediamo a dati
    // decodificati.
    str := `{"pagina": 1, "frutti": ["mela", "pesca"]}`
    res := Response2{}
    json.Unmarshal([]byte(str), &res)
    fmt.Println(res)
    fmt.Println(res.Frutti[0])

    // Negli esempi precedenti abbiamo sempre usato i byte
    // e le stringhe come tramiti tra i dati e la
    // rappresentazione JSON sullo standard output.
    // Possiamo anche indirizzare la codifica JSON
    // direttamente a degli `io.Writer` come `os.Stdout`
    // o addirittura nei corpi delle risposte HTTP.
    enc := json.NewEncoder(os.Stdout)
    d := map[string]int{"mela": 5, "lettuce": 7}
    enc.Encode(d)
}
$ go run json.go
true
1
2.34
"gopher"
["mela","pesca","pera"]
{"lattuga":7,"mela":5}
{"Pagina":1,"Frutti":["mela","pesca","pera"]}
{"pagina":1,"frutti":["mela","pesca","pera"]}
map[num:6.13 strs:[a b]]
6.13
a
{1 [mela pesca]}
mela
{"lettuce":7,"mela":5}


# In questo esempio abbiamo visto i fondamentali del
# JSON in Go, ma per avere ulteriori informazioni
# dai un'occhiata al blog post [JSON and Go](http://blog.golang.org/2011/01/json-and-go.html)
# e alla documentazione del [pacchetto JSON](http://golang.org/pkg/encoding/json/)