Conversione di Go struct in JSON


181

Sto cercando di convertire una struttura Go in JSON usando il jsonpacchetto, ma tutto quello che ottengo è {}. Sono certo che sia qualcosa di totalmente ovvio ma non lo vedo.

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    name string
}

func main() {
    user := &User{name:"Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Printf("Error: %s", err)
        return;
    }
    fmt.Println(string(b))
}

Quindi quando provo a eseguirlo ottengo questo:

$ 6g test.go && 6l -o test test.6 && ./test 
{}

Risposte:


331

È necessario esportare il User.namecampo in modo che il jsonpacchetto possa vederlo. Rinomina il namecampo in Name.

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    Name string
}

func main() {
    user := &User{Name: "Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(b))
}

Produzione:

{"Name":"Frank"}

87
Si noti che è possibile aggiungere `json:"name"`alla fine della definizione del campo struct per conservare il nome dell'output.
Dustin,

12
Vedo. Mi piace il linguaggio ma penso che alcuni elementi sintattici vadano molto lontano. Se il nome di un membro struct determina il comportamento, questo è semplicemente sbagliato.
magiconair,

1
Bene, avere il nome che determina il comportamento può essere discusso se è buono o cattivo :) ma sicuramente rende facile sapere se un campo viene esportato o meno senza dover controllare altrove.
Olof,

6
@magiconair: la capitalizzazione della prima runa determina la visibilità , è un'idea molto più ragionevole di "il nome di un membro di una struttura determina il comportamento" . I metadati di visibilità devono essere archiviati da qualche parte e hanno bisogno della sintassi per esprimerlo. Alla fine è stato determinato che la cooptazione della capitalizzazione del primo carattere funziona meglio con il minor numero di compromessi. Prima del rilascio di Go1, altri schemi venivano provati e respinti.
deft_code

11
Ho fatto molta strada da allora e mi piace molto la lingua, inclusa l'esportazione per capitalizzazione.
magiconair,

62

Problema correlato:

Ho avuto difficoltà a convertire Struct in JSON, inviandolo come risposta da Golang, quindi, in seguito, ho acquisito lo stesso in JavaScript tramite Ajax.

Ha perso molto tempo, quindi pubblicando la soluzione qui.

In Go:

// web server

type Foo struct {
    Number int    `json:"number"`
    Title  string `json:"title"`
}

foo_marshalled, err := json.Marshal(Foo{Number: 1, Title: "test"})
fmt.Fprint(w, string(foo_marshalled)) // write response to ResponseWriter (w)

In JavaScript:

// web call & receive in "data", thru Ajax/ other

var Foo = JSON.parse(data);
console.log("number: " + Foo.number);
console.log("title: " + Foo.title);

Spero che questo aiuti qualcuno.
Buona fortuna.


6

I valori di Struct codificano come oggetti JSON. Ogni campo struct esportato diventa un membro dell'oggetto a meno che:

  • il tag del campo è "-", oppure
  • il campo è vuoto e il suo tag specifica l'opzione "omitempty".

I valori vuoti sono false, 0, qualsiasi puntatore zero o valore dell'interfaccia e qualsiasi array, slice, mappa o stringa di lunghezza zero. La stringa di chiave predefinita dell'oggetto è il nome del campo struct ma può essere specificato nel valore del tag del campo struct. La chiave "json" nel valore del tag del campo struct è il nome della chiave, seguito da una virgola e da opzioni opzionali.


2

Puoi definire i tuoi metodi MarshalJSON e UnmarshalJSON personalizzati e controllare intenzionalmente ciò che dovrebbe essere incluso, ad esempio:

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    name string
}

func (u *User) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        Name     string `json:"name"`
    }{
        Name:     "customized" + u.name,
    })
}

func main() {
    user := &User{name: "Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(b))
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.