Szukaj…
Składnia
- func Marshal (v interface {}) ([] bajt, błąd)
- func Unmarshal (data [] bajt, v interfejs {}) błąd
Uwagi
Pakiet "encoding/json"
Pakiet json implementuje kodowanie i dekodowanie obiektów JSON w Go
.
Typy w JSON wraz z odpowiadającymi im konkretnymi typami w Go to:
Typ JSON | Wybierz rodzaj betonu |
---|---|
boolean | bool |
liczby | float64 lub int |
strunowy | strunowy |
zero | zero |
Podstawowe kodowanie JSON
json.Marshal
z pakietu "encoding/json"
koduje wartość do JSON.
Ten parametr jest wartością do zakodowania. Zwracane wartości to tablica bajtów reprezentujących dane wejściowe zakodowane w JSON (w przypadku powodzenia) i błąd (w przypadku niepowodzenia).
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"]"
Oto kilka podstawowych przykładów kodowania wbudowanych typów danych:
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}
Kodowanie prostych zmiennych pomaga zrozumieć, jak działa kodowanie JSON w Go. Jednak w prawdziwym świecie prawdopodobnie kodujesz bardziej złożone dane przechowywane w strukturach .
Podstawowe dekodowanie JSON
json.Unmarshal
z pakietu "encoding/json"
dekoduje wartość JSON na wartość wskazywaną przez daną zmienną.
Parametry to wartość do zdekodowania w []bytes
i zmienna, która ma być używana jako pamięć dla wartości bez serializacji. Zwrócona wartość jest błędem (w przypadku awarii).
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]
Zauważ, że w powyższym przykładzie z góry znaliśmy zarówno rodzaj klucza, jak i wartość. Lecz nie zawsze tak jest. W rzeczywistości w większości przypadków JSON zawiera mieszane typy wartości.
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"
W ostatnim przykładzie powyżej użyliśmy ogólnej mapy do przechowywania zdekodowanej wartości. Musimy użyć map[string]interface{}
ponieważ wiemy, że klucze są łańcuchami, ale nie znamy z góry rodzaju ich wartości.
Jest to bardzo proste podejście, ale również bardzo ograniczone. W świecie rzeczywistym dekodowałbyś JSON na niestandardowy typ struct
.
Dekodowanie danych JSON z pliku
Dane JSON można również odczytać z plików.
Załóżmy, że mamy plik o nazwie data.json
o następującej treści:
[
{
"Name" : "John Doe",
"Standard" : 4
},
{
"Name" : "Peter Parker",
"Standard" : 11
},
{
"Name" : "Bilbo Baggins",
"Standard" : 150
}
]
Poniższy przykład czyta plik i dekoduje zawartość:
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)
}
}
Plik data.json
musi znajdować się w tym samym katalogu programu wykonywalnego Go. Przeczytaj dokumentację We / Wy pliku Go, aby uzyskać więcej informacji na temat pracy z plikami w Go.
Korzystanie z anonimowych struktur do dekodowania
Celem korzystania z anonimowych struktur jest odkodowanie tylko tych informacji, na których nam zależy, bez zaśmiecania naszej aplikacji typami używanymi tylko w jednej funkcji.
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)
Dane wyjściowe: {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}}]}
Ogólny przypadek zobacz także: http://stackoverflow.com/documentation/go/994/json/4111/encoding-decoding-go-structs
Konfigurowanie pól struktury JSON
Rozważ następujący przykład:
type Company struct {
Name string
Location string
}
Ukryj / pomiń niektóre pola
Aby wyeksportować Revenue
i Sales
, ale ukryć je przed kodowaniem / dekodowaniem, użyj json:"-"
lub zmień nazwę zmiennej, aby rozpocząć od małej litery. Zauważ, że zapobiega to widoczności zmiennej poza pakietem.
type Company struct {
Name string `json:"name"`
Location string `json:"location"`
Revenue int `json:"-"`
sales int
}
Zignoruj puste pola
Aby zapobiec Location
przed zawarte w JSON, gdy jest on ustawiony na wartość zerową, należy dodać ,omitempty
do json
tagu.
type Company struct {
Name string `json:"name"`
Location string `json:"location,omitempty"`
}
Gromadzenie struktur z polami prywatnymi
Jako dobry programista stworzyłeś następującą strukturę z polami wyeksportowanymi i nieeksportowanymi:
type MyStruct struct {
uuid string
Name string
}
Przykład na placu zabaw: https://play.golang.org/p/Zk94Il2ANZ
Teraz chcesz Marshal()
tę strukturę do prawidłowego JSON do przechowywania w coś takiego jak etcd. Jednak ponieważ uuid
nie jest eksportowany, json.Marshal()
pomija go. Co robić? Użyj anonimowej struktury i interfejsu json.MarshalJSON()
! Oto przykład:
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
}
Przykład w Playground: https://play.golang.org/p/Bv2k9GgbzE
Kodowanie / dekodowanie za pomocą struktur Go
Załóżmy, że mamy następującą struct
która definiuje typ City
:
type City struct {
Name string
Temperature int
}
Możemy kodować / dekodować wartości City za pomocą pakietu encoding/json
.
Przede wszystkim musimy użyć metadanych Go, aby poinformować koder o zgodności między polami strukturalnymi a kluczami 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
}
Aby uprościć ten przykład, zadeklarujemy wyraźną korespondencję między polami a kluczami. Można jednak użyć kilku wariantów json:
metadanych, jak wyjaśniono w dokumentacji .
WAŻNE: Tylko wyeksportowane pola (pola z nazwą kapitału) będą serializowane / deserializowane. Na przykład, jeśli nazwiesz pole t emperatura , zostanie ono zignorowane, nawet jeśli ustawisz metadane json
.
Kodowanie
Aby zakodować strukturę City
, użyj json.Marshal
jak w podstawowym przykładzie:
// 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}
Rozszyfrowanie
Aby zdekodować strukturę City
, użyj json.Unmarshal
jak w podstawowym przykładzie:
// 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}