我想自定义结构的编码格式但出错: json:为类型main.Info调用MarshalJSON时出错:文字中的无效字符'o'为false(期待'a') 我的代码出了什么问题?
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
)
type Info struct {
name string
flag bool
}
func (i Info) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
b.Write([]byte(i.name))
if i.flag {
b.Write([]byte(`"true"`))
} else {
b.Write([]byte(`"false"`))
}
return b.Bytes(), nil
}
func main() {
a := []Info{
{"foo", true},
{"bar", false},
}
out, err := json.Marshal(a)
if err != nil {
log.Fatal(err)
}
fmt.Printf(string(out))
}
答案 0 :(得分:2)
您的代码生成无效的JSON文本。
您也应该写出字段的名称,为了安全起见,字段名称和string
值但不引用bool
值(否则Go json
包不会将其解组为bool
(例如)。同样将您的值括在括号{}
中,如下所示:
b.Write([]byte(`{"name":"`)) // started with {
b.Write([]byte(i.name))
b.Write([]byte(`","flag":`)) // note the , between values
if i.flag {
b.Write([]byte(`true`)) // don't quote boolean value
} else {
b.Write([]byte(`false`)) // don't quote boolean value
}
b.Write([]byte(`}`)) // must close with }
输出(尝试Go Playground上的完整申请):
[{"name":"foo","flag":true},{"name":"bar","flag":false}]
但是因为你在编组期间没有做任何特别的事情,只需导出字段(通过用大写字母开头),json
包将自动编组/解组它:
type Info struct {
Name string
Flag bool
}
在Go Playground上试用此版本。
输出(请注意大写字母"Name"
和"Flag"
):
[{"Name":"foo","Flag":true},{"Name":"bar","Flag":false}]
如果要在JSON文本中使用不同的名称,也可以使用标记,如下所示:
type Info struct {
Name string `json:"name"`
Flag bool `json:"flag"`
}
这将再次产生一个带有较低名称的输出:
[{"name":"foo","flag":true},{"name":"bar","flag":false}]
阅读json.Marshal()
函数的文档,了解使用struct标签可以执行的其他选项和自定义。
答案 1 :(得分:0)
将自己的字符串写入缓冲区会消除json.Marshal()
的目的。也许是这样的:
type Info struct {
Name string `json:"name"` // Struct fields should have capital first letter
// if you want it to be found by the marshaller.
Flag bool `json:"flag"` // json:"flag" assigns the object key in json format
}
然后像:
myInfo := Info {
Name: "Foo",
Flag: true,
}
slc, _ := json.Marshal(myInfo)
fmt.Println(string(slc))
答案 2 :(得分:0)
问题在于,在MarshalJSON
的实施过程中,您期望为您带来很多神奇的事情。不幸的是,您需要查看它,就像您从头开始构建字符串一样。意思是这个;
func (i Info) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
b.Write([]byte(i.name))
if i.flag {
b.Write([]byte(`"true"`))
} else {
b.Write([]byte(`"false"`))
}
return b.Bytes(), nil
}
需要看起来更像这样;
func (i Info) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
b.Write([]byte(`{"name":"`))
b.Write([]byte(i.name))
b.Write([]byte(`","flag":`))
if i.flag {
b.Write([]byte(`"true"`))
} else {
b.Write([]byte(`"false"`))
}
b.Write([]byte(`}`))
}
另外,我假设你合法地想要一个字符串作为布尔值(否则为什么要实现这个方法,对吧?),如果没有,那么你会想要摆脱if而只是使用{{1 }}