Konwertowanie Go struct na JSON

181

Próbuję przekonwertować strukturę Go na JSON przy użyciu jsonpakietu, ale wszystko, co dostaję, to {}. Jestem pewien, że jest to coś całkowicie oczywistego, ale nie widzę tego.

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))
}

Potem, gdy próbuję go uruchomić, otrzymuję to:

$ 6g test.go && 6l -o test test.6 && ./test 
{}
magiconair
źródło

Odpowiedzi:

330

Trzeba wyeksportować w User.namepole tak, że jsonpakiet może go zobaczyć. Zmień nazwę namepola na 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))
}

Wynik:

{"Name":"Frank"}
peterSO
źródło
87
Zauważ, że możesz dodać `json:"name"`na końcu definicji pola struct, aby zachować nazwę wyjściową.
Dustin
12
Widzę. Trochę mi się podoba ten język, ale myślę, że niektóre elementy składniowe idą za daleko. Jeśli nazwa członka struktury określa zachowanie, jest to po prostu niepoprawne.
magiconair,
1
Cóż, posiadanie nazwy decyduje o tym, czy zachowanie może być omówione, czy jest dobre, czy złe :), ale z pewnością ułatwia sprawdzenie, czy pole jest eksportowane, czy nie, bez konieczności sprawdzania gdzie indziej.
Olof
6
@magiconair: Wielkie litery pierwszej runy decydują o widoczności , jest znacznie bardziej rozsądnym pomysłem niż: „nazwa członka struktury określa zachowanie” . Metadane widoczności muszą być gdzieś przechowywane i wymagają wyrażenia, aby je wyrazić. Ostatecznie ustalono, że wybór dużej litery pierwszego znaku najlepiej sprawdza się przy najmniejszej liczbie kompromisów. Przed wydaniem Go1 wypróbowano i odrzucono inne programy.
deft_code
11
Przeszedłem długą drogę i bardzo podoba mi się ten język, w tym eksportowanie według wielkich liter.
magiconair
62

Powiązany problem:

Miałem problem z konwersją struct na JSON, wysyłając go jako odpowiedź od Golanga, a potem złapałem to samo w JavaScript przez Ajax.

Zmarnowałem dużo czasu, więc opublikuj rozwiązanie tutaj.

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)

W JavaScript:

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

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

Mam nadzieję, że to komuś pomoże.
Powodzenia.

Manohar Reddy Poreddy
źródło
6

Wartości struktur kodowane są jako obiekty JSON. Każde wyeksportowane pole struktury staje się członkiem obiektu, chyba że:

  • znacznik pola to „-” lub
  • pole jest puste, a jego znacznik określa opcję „pomiń pusty”.

Puste wartości to false, 0, dowolny wskaźnik zerowy lub wartość interfejsu oraz dowolna tablica, plasterek, mapa lub łańcuch o długości zero. Domyślny ciąg klucza obiektu to nazwa pola strukturalnego, ale można go określić w wartości znacznika pola strukturalnego. Klucz „json” w wartości znacznika pola struct to nazwa klucza, po której następuje opcjonalny przecinek i opcje.

GoLang Master
źródło
2

Możesz zdefiniować własne niestandardowe metody MarshalJSON i UnmarshalJSON i celowo kontrolować, co powinno być uwzględnione, np .:

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))
}
Hieu Vo
źródło