在三消项目开发过程中,使用golang中的"encoding/json"包对struct结构体进行序列化,期望得到一个json string类型的字符串,但是打印的输出结果是[123 125]。
模拟示例:
package main
import (
"encoding/json"
"fmt"
"runtime"
)
type user struct {
name string `json: name`
age uint8 `json: age`
}
func main() {
bbq := user{
name: "bbq",
age: 17,
}
jsonStr, err := json.Marshal(bbq)
if err != nil {
fmt.Printf("err = %v\n", err)
return
}
fmt.Printf("jsonStr = %v\n", jsonStr)
}
打印结果:
期望结果:
原因分析
我们直接看下json.Marshal的代码:
可以看到,Marshal返回的值[]byte,即一个ASCII码的byte数组,[123 125]实际就是 { },[]byte类型想打印出可读的字符串,显然需要转换,我们采用string(jsonStr)的标准转换方式,打印出来的结果就是:
目前为止仅解决了打印结果不易读的问题,为什么是空json串呢,go的源码注释非常清晰,在Marshal的注释中,找到这样一段话:
Each exported struct field becomes a member of the object,只有可导出的struct 字段才能成为json对象中的key,golang中,struct可导出的字段,是需要开头字母大写的,回过头来看项目代码,可以看到目前是小写的,
因为当时考虑这个结构体并不需要被外部访问,因此是小写的,没想到json.Marshal要求是大写才能转化。
解决方案
1、struct结构体中的字段名首字母大写
2、json.Marshal序列化后再做一次字符串类型转化,string()
示例代码修正:
package main
import (
"encoding/json"
"fmt"
)
type user struct {
Name string `json: name`
Age uint8 `json: age`
}
func main() {
bbq := user{
Name: "bbq",
Age: 17,
}
jsonStr, err := json.Marshal(bbq)
if err != nil {
fmt.Printf("err = %v\n", err)
return
}
fmt.Printf("jsonStr = %s\n", string(jsonStr))
}