记录golang序列化中使用的几个注意点

变量的大小写

go中根据首字母的大小写来确定可以访问的权限。如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用。包括接口、类型、函数和变量等。

可以简单的理解成,首字母大写是公有的,首字母小写是私有的

type Student struct {
	name string
	Id int
	Major string
}

func main() {
	testStruct := Student{
		name:  "zhangsan",
		Id:    34254,
		Major: "Computer Science",
	}
	jsonStr, err := json.Marshal(testStruct)
	if err == nil {
		fmt.Println("result: ",string(jsonStr))
	}else {
		fmt.Println("error occur", err)
	}
}

  执行的结果result: {"Id":34254,"Major":"Computer Science"}, 发现name根本没有被序列化进去;将首字母改成大写后,则成功序列化result: {"Name":"zhangsan","Id":34254,"Major":"Computer Science"}

type Student struct {
	Name string
	Id int
	Major string
}

func main() {
	testStruct := Student{
		Name:  "zhangsan",
		Id:    34254,
		Major: "Computer Science",
	}
	jsonStr, err := json.Marshal(testStruct)
	if err == nil {
		fmt.Println("result: ",string(jsonStr))
	}else {
		fmt.Println("error occur", err)
	}
}

map反序列化精度损失

现象

下面代码执行的结果,会得到后面的输出,可以看到,id的大数字被unmarshal转化成float64类型,从而出现了精度缺失

a := `{"id":280123412341234123}`
fmt.Printf("a:%v\n", a)

para := make(map[string]interface{})

err := json.Unmarshal([]byte(a), &para)

fmt.Printf("para:%v, err:%v\n", para, err)

id := int64(para["id"].(float64))

fmt.Printf("id:%v\n", id)
a:{"id":280123412341234123}
para:map[id:2.801234123412341e+17], err:<nil>
id:280123412341234112

 原因

在解析int型数据的过程中,采取了float64来存储了数字

// convertNumber converts the number literal s to a float64 or a Number
// depending on the setting of d.useNumber.
func (d *decodeState) convertNumber(s string) (interface{}, error) {
	if d.useNumber {
		return Number(s), nil
	}
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)}
	}
	return f, nil
}

解决方案

使用decoder,不能直接unmarshal

func main() {
	a := `{"id":280123412341234123}`
	fmt.Printf("a:%v\n", a)
	para := make(map[string]interface{})
	decoder := json.NewDecoder(strings.NewReader(a))
	decoder.UseNumber()
	err := decoder.Decode(&para)
	fmt.Printf("para:%v, err:%v\n", para, err)
	id, err := para["id"].(json.Number).Int64()
	fmt.Printf("id:%v, err:%v\n", id, err)
}

  

posted @ 2020-05-08 14:26  二十三年蝉Ssss  阅读(261)  评论(0)    收藏  举报