Zoeken…
Syntaxis
- func Marshal (v interface {}) ([] byte, fout)
- func Unmarshal (data [] byte, v interface {}) fout
Opmerkingen
Het pakket "encoding/json"
Pakket json implementeert codering en decodering van JSON-objecten in Go
.
Typen in JSON samen met hun bijbehorende betonsoorten in Go zijn:
JSON Type | Ga concreet type |
---|---|
boolean | bool |
getallen | float64 of int |
draad | draad |
nul | nul |
Basis JSON-codering
json.Marshal
uit het pakket "encoding/json"
codeert een waarde voor JSON.
De parameter is de te coderen waarde. De geretourneerde waarden zijn een array van bytes die de JSON-gecodeerde invoer vertegenwoordigen (bij succes) en een fout (bij mislukking).
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"]"
Hier zijn enkele basisvoorbeelden van codering voor ingebouwde gegevenstypen:
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}
Het coderen van eenvoudige variabelen is handig om te begrijpen hoe de JSON-codering werkt in Go. In de echte wereld zul je echter waarschijnlijk complexere gegevens coderen die zijn opgeslagen in structs .
Basic JSON-decodering
json.Unmarshal
uit het pakket "encoding/json"
decodeert een JSON-waarde in de waarde die wordt aangegeven door de gegeven variabele.
De parameters zijn de te decoderen waarde in []bytes
en een variabele die moet worden gebruikt als opslag voor de gedeserialiseerde waarde. De geretourneerde waarde is een fout (bij mislukking).
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]
Merk op hoe we in het bovenstaande voorbeeld van tevoren zowel het type sleutel als de waarde wisten. Maar dit is niet altijd het geval. In feite bevat de JSON in de meeste gevallen typen met gemengde waarden.
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"
In het laatste voorbeeld hierboven hebben we een generieke kaart gebruikt om de gedecodeerde waarde op te slaan. We moeten een map[string]interface{}
omdat we weten dat de sleutels tekenreeksen zijn, maar we weten niet van tevoren het type van hun waarden.
Dit is een heel eenvoudige aanpak, maar het is ook extreem beperkt. In de echte wereld zou u over het algemeen een JSON decoderen naar een op maat gedefinieerd struct
type .
JSON-gegevens decoderen uit een bestand
JSON-gegevens kunnen ook uit bestanden worden gelezen.
Laten we aannemen dat we een bestand met de naam data.json
met de volgende inhoud:
[
{
"Name" : "John Doe",
"Standard" : 4
},
{
"Name" : "Peter Parker",
"Standard" : 11
},
{
"Name" : "Bilbo Baggins",
"Standard" : 150
}
]
In het volgende voorbeeld wordt het bestand gelezen en wordt de inhoud gedecodeerd:
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)
}
}
Het bestand data.json
moet zich in dezelfde map bevinden als het uitvoerbare programma Go. Lees Go File I / O-documentatie voor meer informatie over het werken met bestanden in Go.
Anonieme structs gebruiken voor het decoderen
Het doel met het gebruik van anonieme structuren is om alleen de informatie te decoderen waar we om geven, zonder onze app te vervuilen met typen die alleen in één functie worden gebruikt.
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}}]}
Zie voor het algemene geval ook: http://stackoverflow.com/documentation/go/994/json/4111/encoding-decoding-go-structs
JSON struct-velden configureren
Overweeg het volgende voorbeeld:
type Company struct {
Name string
Location string
}
Bepaalde velden verbergen / overslaan
Om Revenue
en Sales
te exporteren, maar ze te verbergen voor codering / decodering, gebruikt u json:"-"
of hernoemt u de variabele om met een kleine letter te beginnen. Merk op dat dit voorkomt dat de variabele zichtbaar is buiten het pakket.
type Company struct {
Name string `json:"name"`
Location string `json:"location"`
Revenue int `json:"-"`
sales int
}
Negeer lege velden
Om te voorkomen dat Location
wordt opgenomen in de JSON wanneer deze is ingesteld op de nulwaarde, voegt u ,omitempty
aan de json
tag.
type Company struct {
Name string `json:"name"`
Location string `json:"location,omitempty"`
}
Marshal structs met privévelden
Als een goede ontwikkelaar heb je de volgende struct gemaakt met zowel geëxporteerde als niet-geëxporteerde velden:
type MyStruct struct {
uuid string
Name string
}
Voorbeeld in Playground: https://play.golang.org/p/Zk94Il2ANZ
Nu wil je Marshal()
deze struct in geldige JSON voor opslag in zoiets als etcd. Echter, aangezien uuid
in niet geëxporteerd, de json.Marshal()
slaat het. Wat te doen? Gebruik een anonieme struct en de json.MarshalJSON()
interface! Hier is een voorbeeld:
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
}
Voorbeeld in Playground: https://play.golang.org/p/Bv2k9GgbzE
Coderen / decoderen met behulp van Go-structs
Laten we aannemen dat we hebben de volgende struct
die een definieert City
soort:
type City struct {
Name string
Temperature int
}
We kunnen City-waarden coderen / decoderen met behulp van het encoding/json
pakket.
Allereerst moeten we de Go-metagegevens gebruiken om de encoder de correspondentie tussen de struct-velden en de JSON-sleutels te vertellen.
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
}
Om dit voorbeeld eenvoudig te houden, verklaren we een expliciete overeenkomst tussen de velden en de toetsen. U kunt echter verschillende varianten van de json:
metadata gebruiken, zoals uitgelegd in de documenten .
BELANGRIJK: alleen geëxporteerde velden (velden met hoofdnaam) worden geserialiseerd / gedeserialiseerd. Als u bijvoorbeeld het veld t emperature een naam geeft , wordt het genegeerd, zelfs als u de json
metagegevens json
.
codering
Om een te coderen City
structuur, gebruik json.Marshal
zoals in het eenvoudig voorbeeld:
// 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}
decoderen
Om een decoderen City
structuur, gebruik json.Unmarshal
zoals in het eenvoudig voorbeeld:
// 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}