Преобразование структуры Go в JSON

181

Я пытаюсь преобразовать структуру Go в JSON, используя jsonпакет, но все, что я получаю, это {}. Я уверен, что это нечто совершенно очевидное, но я этого не вижу.

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

Затем, когда я пытаюсь запустить его, я получаю это:

$ 6g test.go && 6l -o test test.6 && ./test 
{}
magiconair
источник

Ответы:

331

Вам нужно экспортировать в User.nameполе , так что jsonпакет может увидеть его. Переименуйте nameполе в 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))
}

Вывод:

{"Name":"Frank"}
peterSO
источник
87
Обратите внимание, что вы можете добавить `json:"name"`в конец определения структуры поля, чтобы сохранить выходное имя.
Дастин
12
Понимаю. Я вроде как язык, но я думаю, что некоторые синтаксические элементы идут далеко. Если имя члена структуры определяет поведение, то это просто неправильно.
magiconair
1
То, что имя определяет поведение, можно обсудить, хорошо это или плохо :), но это, несомненно, позволяет легко узнать, экспортируется ли поле или нет, без необходимости проверять где-то еще.
Олоф
6
@magiconair: заглавная буква первой руны определяет видимость , это гораздо более разумная идея, чем «имя члена структуры определяет поведение» . Метаданные видимости должны храниться где-то и иметь синтаксис для их выражения. В конце концов было установлено, что использование заглавных букв первого символа работает лучше всего с наименьшим количеством компромиссов. Перед выпуском Go1 другие схемы были опробованы и отклонены.
deft_code
11
С тех пор я прошел долгий путь, и теперь мне очень нравится язык, в том числе экспорт по капитализации.
magiconair
62

Связанная проблема:

У меня возникли проблемы с преобразованием структуры в JSON, отправкой его в виде ответа от Golang, а затем перехватить то же самое в JavaScript через Ajax.

Потрачено много времени, поэтому выкладываю решение здесь.

На ходу:

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

В JavaScript:

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

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

Надеюсь, это кому-нибудь поможет.
Удачи.

Манохар Редди Поредди
источник
6

Структурные значения кодируются как объекты JSON. Каждое экспортированное поле структуры становится членом объекта, если:

  • тег поля "-" или
  • поле пустое, а его тег определяет опцию «omitempty».

Пустыми значениями являются false, 0, любой нулевой указатель или значение интерфейса, а также любой массив, срез, карта или строка нулевой длины. Строка ключа объекта по умолчанию - это имя структурного поля, но оно может быть указано в значении тега структурного поля. Ключ "json" в значении тега поля struct представляет собой имя ключа, за которым следует необязательная запятая и параметры.

GoLang Master
источник
2

Вы можете определить свои собственные методы MarshalJSON и UnmarshalJSON и преднамеренно контролировать то, что должно быть включено, например:

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))
}
Хиеу Во
источник