Ricerca…
Sintassi
- func Marshal (v interface {}) ([] byte, errore)
- func Errore Unmarshal (data [] byte, v interfaccia {})
Osservazioni
Il pacchetto "encoding/json"
Package json implementa la codifica e la decodifica degli oggetti JSON in Go
.
I tipi in JSON insieme ai tipi di calcestruzzo corrispondenti in Go sono:
Tipo JSON | Vai tipo di cemento |
---|---|
booleano | bool |
numeri | float64 o int |
stringa | stringa |
nullo | zero |
Codifica JSON di base
json.Marshal
dal pacchetto "encoding/json"
codifica un valore per JSON.
Il parametro è il valore da codificare. I valori restituiti sono una matrice di byte che rappresentano l'input codificato JSON (in caso di successo) e un errore (in caso di errore).
decodedValue := []string{"foo", "bar"}
// encode the value
data, err := json.Marshal(decodedValue)
// check if the encoding is successful
if err != nil {
panic(err)
}
// print out the JSON-encoded string
// remember that data is a []byte
fmt.Println(string(data))
// "["foo","bar"]"
Ecco alcuni esempi di base di codifica per i tipi di dati incorporati:
var data []byte
data, _ = json.Marshal(1)
fmt.Println(string(data))
// 1
data, _ = json.Marshal("1")
fmt.Println(string(data))
// "1"
data, _ = json.Marshal(true)
fmt.Println(string(data))
// true
data, _ = json.Marshal(map[string]int{"London": 18, "Rome": 30})
fmt.Println(string(data))
// {"London":18,"Rome":30}
La codifica di variabili semplici è utile per capire come funziona la codifica JSON in Go. Tuttavia, nel mondo reale, probabilmente codificherete dati più complessi memorizzati nelle strutture .
Decodifica JSON di base
json.Unmarshal
dal pacchetto "encoding/json"
decodifica un valore JSON nel valore indicato dalla variabile data.
I parametri sono il valore da decodificare in []bytes
e una variabile da utilizzare come memoria per il valore de-serializzato. Il valore restituito è un errore (in caso di errore).
encodedValue := []byte(`{"London":18,"Rome":30}`)
// generic storage for the decoded JSON
var data map[string]interface{}
// decode the value into data
// notice that we must pass the pointer to data using &data
err := json.Unmarshal(encodedValue, &data)
// check if the decoding is successful
if err != nil {
panic(err)
}
fmt.Println(data)
map[London:18 Rome:30]
Si noti come nell'esempio precedente abbiamo saputo in anticipo sia il tipo di chiave che il valore. Ma questo non è sempre il caso. Di fatto, nella maggior parte dei casi il JSON contiene tipi di valori misti.
encodedValue := []byte(`{"city":"Rome","temperature":30}`)
// generic storage for the decoded JSON
var data map[string]interface{}
// decode the value into data
if err := json.Unmarshal(encodedValue, &data); err != nil {
panic(err)
}
// if you want to use a specific value type, we need to cast it
temp := data["temperature"].(float64)
fmt.Println(temp) // 30
city := data["city"].(string)
fmt.Println(city) // "Rome"
Nell'ultimo esempio sopra abbiamo usato una mappa generica per memorizzare il valore decodificato. Dobbiamo utilizzare un'interfaccia map[string]interface{}
perché sappiamo che le chiavi sono stringhe, ma non conosciamo il tipo dei loro valori in anticipo.
Questo è un approccio molto semplice, ma è anche estremamente limitato. Nel mondo reale, generalmente decodificare un JSON in un tipo di struct
definito dall'utente .
Decodifica dei dati JSON da un file
I dati JSON possono anche essere letti dai file.
Supponiamo di avere un file chiamato data.json
con il seguente contenuto:
[
{
"Name" : "John Doe",
"Standard" : 4
},
{
"Name" : "Peter Parker",
"Standard" : 11
},
{
"Name" : "Bilbo Baggins",
"Standard" : 150
}
]
L'esempio seguente legge il file e decodifica il contenuto:
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Student struct {
Name string
Standard int `json:"Standard"`
}
func main() {
// open the file pointer
studentFile, err := os.Open("data.json")
if err != nil {
log.Fatal(err)
}
defer studentFile.Close()
// create a new decoder
var studentDecoder *json.Decoder = json.NewDecoder(studentFile)
if err != nil {
log.Fatal(err)
}
// initialize the storage for the decoded data
var studentList []Student
// decode the data
err = studentDecoder.Decode(&studentList)
if err != nil {
log.Fatal(err)
}
for i, student := range studentList {
fmt.Println("Student", i+1)
fmt.Println("Student name:", student.Name)
fmt.Println("Student standard:", student.Standard)
}
}
Il file data.json
deve essere nella stessa directory del programma eseguibile Go. Leggi la documentazione di I / O sul file Go per ulteriori informazioni su come lavorare con i file in Go.
Utilizzo di strutture anonime per la decodifica
L'obiettivo con l'utilizzo di strutture anonime è quello di decodificare solo le informazioni che ci interessano senza sporcare la nostra app con tipi che vengono utilizzati solo in una singola funzione.
jsonBlob := []byte(`
{
"_total": 1,
"_links": {
"self": "https://api.twitch.tv/kraken/channels/foo/subscriptions?direction=ASC&limit=25&offset=0",
"next": "https://api.twitch.tv/kraken/channels/foo/subscriptions?direction=ASC&limit=25&offset=25"
},
"subscriptions": [
{
"created_at": "2011-11-23T02:53:17Z",
"_id": "abcdef0000000000000000000000000000000000",
"_links": {
"self": "https://api.twitch.tv/kraken/channels/foo/subscriptions/bar"
},
"user": {
"display_name": "bar",
"_id": 123456,
"name": "bar",
"staff": false,
"created_at": "2011-06-16T18:23:11Z",
"updated_at": "2014-10-23T02:20:51Z",
"logo": null,
"_links": {
"self": "https://api.twitch.tv/kraken/users/bar"
}
}
}
]
}
`)
var js struct {
Total int `json:"_total"`
Links struct {
Next string `json:"next"`
} `json:"_links"`
Subs []struct {
Created string `json:"created_at"`
User struct {
Name string `json:"name"`
ID int `json:"_id"`
} `json:"user"`
} `json:"subscriptions"`
}
err := json.Unmarshal(jsonBlob, &js)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", js)
Output: {Total:1 Links:{Next:https://api.twitch.tv/kraken/channels/foo/subscriptions?direction=ASC&limit=25&offset=25} Subs:[{Created:2011-11-23T02:53:17Z User:{Name:bar ID:123456}}]}
Per il caso generale vedi anche: http://stackoverflow.com/documentation/go/994/json/4111/encoding-decoding-go-struct
Configurazione dei campi struct JSON
Considera il seguente esempio:
type Company struct {
Name string
Location string
}
Nascondi / ignora determinati campi
Per esportare Revenue
e Sales
, ma nasconderli dalla codifica / decodifica, usa json:"-"
o rinomina la variabile per iniziare con una lettera minuscola. Si noti che questo impedisce alla variabile di essere visibile all'esterno del pacchetto.
type Company struct {
Name string `json:"name"`
Location string `json:"location"`
Revenue int `json:"-"`
sales int
}
Ignora campi vuoti
Per evitare che Location
venga incluso nel JSON quando è impostato sul suo valore zero, aggiungi ,omitempty
al tag json
.
type Company struct {
Name string `json:"name"`
Location string `json:"location,omitempty"`
}
Strutture di marshalling con campi privati
Come bravo sviluppatore hai creato la seguente struttura con campi sia esportati che non esportati:
type MyStruct struct {
uuid string
Name string
}
Esempio in Playground: https://play.golang.org/p/Zk94Il2ANZ
Ora vuoi Marshal()
questa struttura in JSON valido per l'archiviazione in qualcosa come ecc. Tuttavia, poiché uuid
non viene esportato, json.Marshal()
salta. Cosa fare? Usa una struttura anonima e l'interfaccia json.MarshalJSON()
! Ecco un esempio:
type MyStruct struct {
uuid string
Name string
}
func (m MyStruct) MarshalJSON() ([]byte, error {
j, err := json.Marshal(struct {
Uuid string
Name string
}{
Uuid: m.uuid,
Name: m.Name,
})
if err != nil {
return nil, err
}
return j, nil
}
Esempio in Playground: https://play.golang.org/p/Bv2k9GgbzE
Codifica / decodifica usando le strutture di Go
Supponiamo di avere la seguente struct
che definisce un tipo di City
:
type City struct {
Name string
Temperature int
}
Possiamo codificare / decodificare i valori della città usando il pacchetto encoding/json
.
Prima di tutto, dobbiamo usare i metadati Go per dire al codificatore la corrispondenza tra i campi struct e le chiavi JSON.
type City struct {
Name string `json:"name"`
Temperature int `json:"temp"`
// IMPORTANT: only exported fields will be encoded/decoded
// Any field starting with a lower letter will be ignored
}
Per mantenere semplice questo esempio, dichiareremo una corrispondenza esplicita tra i campi e le chiavi. Tuttavia, è possibile utilizzare diverse varianti del json:
metadati come spiegato nei documenti .
IMPORTANTE: solo i campi esportati (campi con il nome maiuscolo) verranno serializzati / deserializzati. Ad esempio, se si nomina il campo t emperature , verrà ignorato anche se si impostano i metadati json
.
Codifica
Per codificare una struttura di City
, usa json.Marshal
come nell'esempio di base:
// data to encode
city := City{Name: "Rome", Temperature: 30}
// encode the data
bytes, err := json.Marshal(city)
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
// {"name":"Rome","temp":30}
decodifica
Per decodificare una struttura di City
, usa json.Unmarshal
come nell'esempio di base:
// data to decode
bytes := []byte(`{"name":"Rome","temp":30}`)
// initialize the container for the decoded data
var city City
// decode the data
// notice the use of &city to pass the pointer to city
if err := json.Unmarshal(bytes, &city); err != nil {
panic(err)
}
fmt.Println(city)
// {Rome 30}