将Go结构体转换为JSON

314

我尝试使用json包将Go结构体转换为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 
{}
5个回答

530

你需要导出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"}

134
请注意,在结构体字段定义的末尾添加\json:"name"``可以保留输出名称。 - Dustin
17
我明白了。我有点喜欢这种语言,但我认为有些句法元素太过分了。如果一个结构体成员的名称决定了其行为,那么这就是错误的。 - magiconair
2
名称决定行为的好坏可以有争议 :) 但这确实使得在不必查看其他地方的情况下知道字段是否被导出变得容易。 - Olof
8
“@magiconair: 第一个符文的大写决定了可见性”这个想法比“‘结构体成员的名称决定行为’”更加合理。可见性元数据需要存储在某处,并需要语法来表达它。最终确定,利用第一个字符的大小写最好,牺牲最少。在Go1发布之前,尝试了其他计划,但被拒绝了。 - deft_code
14
自从那时以来,我已经取得了很大进步,现在非常喜欢这种语言,包括利用大写字母进行输出。 - magiconair
1
这很糟糕。这意味着我必须跳过许多障碍才能使代码运行,而之前使用的语言可以轻松地使用小写字段。 - WreckFish

96

相关问题:

我在将结构体转换为JSON并通过Golang作为响应发送,之后通过Ajax在JavaScript中捕获同样的响应时遇到了困难。

浪费了很多时间,所以在这里发布解决方案。

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

在JavaScript中:

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

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

1
"这将以大写字母写入JSON。如何以小写字母编写JSON字符串?" - WreckFish

14

这是一个有趣的问题,使用新版的go非常容易。你应该这样做:

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    Name string `json:"name"`
}

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

将此名称更改为Name。


user := &User{Name: "Frank"} - undefined

10
您可以定义自己的自定义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))
}


7

结构体值被编码为JSON对象。每个导出的结构体字段都成为该对象的成员,除非:

  • 字段的标签为“-”,或
  • 该字段为空且其标签指定了“omitempty”选项。

空值是false、0、任何nil指针或接口值以及长度为零的任何数组、切片、映射或字符串。对象的默认键名是结构体字段名,但可以在结构体字段的标签值中指定。“json”关键字在结构体字段的标签值中是键名,后跟可选的逗号和选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接