Convertendo Go struct para JSON

181

Estou tentando converter uma estrutura Go para JSON usando o jsonpacote, mas tudo o que recebo é {}. Estou certo de que é algo totalmente óbvio, mas não o vejo.

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

Então, quando tento executá-lo, recebo o seguinte:

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

Respostas:

331

Você precisa exportar o User.namecampo para que o jsonpacote possa vê-lo. Renomeie o namecampo para 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))
}

Resultado:

{"Name":"Frank"}
peterSO
fonte
87
Observe que você pode adicionar `json:"name"`ao final da definição do campo struct para preservar o nome da saída.
Dustin
12
Entendo. Eu meio que gosto da linguagem, mas acho que alguns elementos sintáticos vão longe. Se o nome de um membro struct determina o comportamento, isso está errado.
magiconair
1
Bem, ter o nome determinar o comportamento pode ser debatido se é bom ou ruim :), mas com certeza facilita saber se um campo é exportado ou não sem ter que verificar em outro lugar.
Olof
6
@magiconair: A capitalização da primeira runa determina a visibilidade , é uma idéia muito mais razoável do que "o nome de um membro da estrutura determina o comportamento" . Os metadados de visibilidade precisam ser armazenados em algum lugar e precisam de sintaxe para expressá-los. Por fim, foi determinado que a opção de capitalização do primeiro caractere funciona melhor com o menor número de trocas. Antes do lançamento do Go1, outros esquemas eram tentados e rejeitados.
Deft_code
11
Percorri um longo caminho desde então e gosto muito do idioma, incluindo a exportação por capitalização.
magiconair
62

Assunto relacionado:

Eu estava tendo problemas para converter struct em JSON, enviando-o como resposta da Golang e depois capturando o mesmo em JavaScript via Ajax.

Perdi muito tempo, então postando a solução aqui.

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

Em JavaScript:

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

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

Espero que isso ajude alguém.
Boa sorte.

Manohar Reddy Poreddy
fonte
6

Os valores de estrutura são codificados como objetos JSON. Cada campo de estrutura exportado se torna um membro do objeto, a menos que:

  • a tag do campo é "-" ou
  • o campo está vazio e sua tag especifica a opção "omitempty".

Os valores vazios são falsos, 0, qualquer ponteiro nulo ou valor de interface e qualquer matriz, fatia, mapa ou sequência de comprimento zero. A cadeia de chave padrão do objeto é o nome do campo struct, mas pode ser especificada no valor da tag do campo struct. A chave "json" no valor da tag do campo struct é o nome da chave, seguido por uma vírgula e opções opcionais.

GoLang Master
fonte
2

Você pode definir seus próprios métodos MarshalJSON e UnmarshalJSON personalizados e controlar intencionalmente o que deve ser incluído, por exemplo:

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
fonte