Conversión de Go struct a JSON

181

Estoy tratando de convertir una estructura Go a JSON usando el jsonpaquete, pero todo lo que obtengo es {}. Estoy seguro de que es algo totalmente obvio, pero no lo veo.

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

Luego, cuando trato de ejecutarlo, obtengo esto:

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

Respuestas:

331

Debe exportar el User.namecampo para que el jsonpaquete pueda verlo. Cambie el nombre del namecampo a 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))
}

Salida:

{"Name":"Frank"}
PeterSO
fuente
87
Tenga en cuenta que puede agregar `json:"name"`al final de la definición del campo de estructura para preservar el nombre de salida.
Dustin
12
Veo. Me gusta un poco el lenguaje, pero creo que algunos elementos sintácticos llegan demasiado lejos. Si el nombre de un miembro de estructura determina el comportamiento, entonces esto es simplemente incorrecto.
magiconair
1
Bueno, hacer que el nombre determine el comportamiento se puede debatir si es bueno o malo :) pero seguro que hace que sea fácil saber si un campo se exporta o no sin tener que consultarlo en otro lugar.
Olof
66
@magiconair: La capitalización de la primera runa determina la visibilidad , es una idea mucho más razonable que "el nombre de un miembro de la estructura determina el comportamiento" . Los metadatos de visibilidad deben almacenarse en algún lugar y necesitan sintaxis para expresarlo. Finalmente, se determinó que cooptar la capitalización del primer personaje funciona mejor con la menor cantidad de compensaciones. Antes del lanzamiento de Go1, se probaron y rechazaron otros esquemas.
deft_code
11
He recorrido un largo camino desde entonces y me gusta mucho el lenguaje, incluida la exportación por capitalización.
magiconair
62

Asunto relacionado:

Estaba teniendo problemas para convertir la estructura a JSON, enviándola como respuesta de Golang, luego, luego capté lo mismo en JavaScript a través de Ajax.

Perdí mucho tiempo, así que publiqué una solución aquí.

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

En 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 esto ayude a alguien.
La mejor de las suertes.

Manohar Reddy Poreddy
fuente
6

Los valores de estructura se codifican como objetos JSON. Cada campo de estructura exportado se convierte en un miembro del objeto a menos que:

  • la etiqueta del campo es "-", o
  • el campo está vacío y su etiqueta especifica la opción "omitempty".

Los valores vacíos son falso, 0, cualquier puntero nulo o valor de interfaz, y cualquier matriz, segmento, mapa o cadena de longitud cero. La cadena de clave predeterminada del objeto es el nombre del campo de estructura, pero se puede especificar en el valor de etiqueta del campo de estructura. La clave "json" en el valor de la etiqueta del campo de estructura es el nombre de la clave, seguido de una coma y opciones opcionales.

GoLang Master
fuente
2

Puede definir sus propios métodos personalizados MarshalJSON y UnmarshalJSON y controlar intencionalmente lo que debe incluirse, por ejemplo:

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
fuente