golang-对json的处理

概要

使用golang对服务器进行部署时,常常涉及对json数据的处理。在golang结构体中提供了json tag,可快速实现对json和struct数据类型之间的快速绑定。本文将探讨golang对json的一些处理技巧

结构体绑定json

使用结构体的tag标签,实现结构体绑定json

  • marshal:序列化,将结构体类型转换成为json协议的byte数组
  • unmarshal:反序列化,将json协议的byte数组转换成为相应的结构体
type Person struct {
	Name   string `json:"name"`
	Age    string `json:"age"`
	Weight string `json:"weight"`
}

func transformation() {
	data_struct := Person{
		Name:   "bob",
		Age:    "23",
		Weight: "160",
	}
	//  将结构体转换成为json
	data_byte, _ := json.Marshal(data_struct)
	fmt.Printf("str:%v\n", string(data_byte))

	var p2 Person
	json.Unmarshal(data_byte, &p2)
	fmt.Printf("struct:%v\n", p2)
}

结构体绑定json——omitempty标签

编写结构体中,如果绑定的json没有对应字段,结构体的字段将会采用默认值
为了更加严格的规定,给结构体加上omitempty标签,如果绑定的json没有对应字段,结构体中将不会出现该字段

// 在tag中不带omitempty,采用默认值
type Game1 struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

// 在tag中带omitempty忽略空值
type Game2 struct {
	Name  string `json:"name"`
	Value string `json:"value,omitempty"`
}

func emptyOperation() {
	var game1 Game1
	var game2 Game2

	game1 = Game1{
		Name: "bob",
	}

	game2 = Game2{
		Name: "james",
	}

	game1_json, _ := json.Marshal(game1)
	game2_json, _ := json.Marshal(game2)

	fmt.Printf("game1 without omitempty:%v\n", string(game1_json))
	fmt.Printf("game2 with omitempty:%v\n", string(game2_json))
}

在这里插入图片描述

嵌套结构体绑定json

  1. 匿名嵌套无json标签,序列化之后的json仅有单层结构(非嵌套结构)
  2. 匿名嵌套带json标签,序列化之后的json有嵌套结构
  3. 具名嵌套带json标签,序列化之后的json有嵌套结构
//	匿名嵌套,指的是在结构体中不指定字段名,只是指定类型的字段
type User struct {
	Name  string   `json:"name"`
	Email string   `json:"email,omitempty"`
	Hobby []string `json:"hobby,omitempty"`
	Profile
}

type User2 struct {
	Name    string   `json:"name"`
	Email   string   `json:"email,omitempty"`
	Hobby   []string `json:"hobby,omitempty"`
	Profile `json:"profile"`
}

type Profile struct {
	Website string `json:"website"`
	Slogan  string `json:"slogan"`
}

func embededStruct() {
	//	匿名嵌套在josn序列化时,会直接输出类型对应的字段(没有相应的嵌套层级)
	profile := Profile{
		Website: "http://www.baidu.com",
		Slogan:  "happpy everyday",
	}
	user := User{
		Name:    "bob",
		Profile: profile,
	}
	user_json, _ := json.Marshal(user)
	fmt.Printf("embededStruct1:%v\n", string(user_json))

	//	具名嵌套或者加入tag标签时,会输出有嵌套层级的json结构
	user2 := User2{
		Name:    "james",
		Profile: profile,
	}
	user2_json, _ := json.Marshal(user2)
	fmt.Printf("embededStruct2:%v\n", string(user2_json))
}

在这里插入图片描述

结构体绑定json——指定解析相应的数据类型

如果struct和json的数据类型不同,但是需要相应的字段进行映射。
此时,可以在标签中指定解析相应的数据类型

//	添加string tag,告诉json包从字符串中解析相应字段的数据
type Card struct {
	ID    int64   `json:"id,string"`
	Score float64 `json:"score,string"`
}

func intAndStringDemo() {
	jsonStr1 := `{"id":"233","score":"100"}`
	var c1 Card
	json.Unmarshal([]byte(jsonStr1), &c1)
	fmt.Printf("card:%v\n", c1)
}

结构体绑定json-数据类型转换

由于json中只有number类型,在golang的反序列化过程中,将json的number类型转换为float型

// json协议中没有int、float型,只有number型,在反序列化后,number型将会被转换成为float型
func jsonDemo() {
	var m = make(map[string]interface{}, 1)
	m["count"] = 1
	b, _ := json.Marshal(m)
	fmt.Printf("str:%#v\n", string(b))

	var m2 map[string]interface{}
	json.Unmarshal(b, &m2)
	fmt.Printf("value:%v\n", m2["count"])
	fmt.Printf("type:%t\n", m2["count"])
}

在这里插入图片描述

自定义marshalJSON、unmarshalJSON方法

在json序列化、反序列化的过程中,需要对一些特殊的字段进行处理。我们可以自定义marshalJSON、unmarshalJSON方法,对time的数据类型进行处理(原json的marshal、unmarshal不支持对 "2006-01-02 15:04:05"的时间格式进行处理)

//	自定义marshalJSON方法和unmarshalJSON方法
type Order struct {
	ID          int       `json:"id"`
	Title       string    `json:"title"`
	CreatedTime time.Time `json:"created_time"`
}

const layout = "2006-01-02 15:04:05"

// 自定义序列化操作
func (o *Order) MarshalJSON() ([]byte, error) {
	type TempOrder Order
	return json.Marshal(struct {
		CreatedTime string `json:"created_time"`
		*TempOrder
	}{
		CreatedTime: o.CreatedTime.Format(layout),
		TempOrder:   (*TempOrder)(o),
	})
}

//	自定义反序列化操作
func (o *Order) UnmarshalJSON(data []byte) error {
	type TempOrder Order
	ot := struct {
		CreatedTime string `json:"created_time"`
		*TempOrder
	}{
		TempOrder: (*TempOrder)(o),
	}

	if err := json.Unmarshal(data, &ot); err != nil {
		return err
	}

	var err error
	o.CreatedTime, err = time.Parse(layout, ot.CreatedTime)
	if err != nil {
		return err
	}
	return nil
}

func customMethodDemo() {
	ol := Order{
		ID:          123456,
		Title:       "Go学习之路",
		CreatedTime: time.Now(),
	}
	b, _ := json.Marshal(&ol)
	fmt.Printf("str:%s\n", b)

	jsonStr := `{"created_time":"2020-04-05 10:18:20","title":"go learning","id":123456}`
	var o2 Order
	if err := json.Unmarshal([]byte(jsonStr), &o2); err != nil {
		fmt.Printf("json.Unmarshal failed, err:%v\n", err)
	}
	fmt.Printf("o2:%v\n", o2)
}

在这里插入图片描述

处理不确定层级的json

如果不确定json的层级,可以使用json.RawMessage进行处理

//	处理不确定层级得json
type sendMSG struct {
	User string `json:"user"`
	Msg  string `json:"msg"`
}

func rawMessageDemo(){
	jsonStr:=`{"sendMSG":{"user":"bob", "msg":"golang learn"}, "say":"hello"}`
	//	定义一个map,value类型为json.RawMessage,方便后续更加灵活的处理
	var data map[string]json.RawMessage
	if err:=json.Unmarshal([]byte(jsonStr), &data);err!=nil{
		fmt.Printf("json.Umarshal jsonStr failed, err:%v\n", err)
		return
	}

	var msg sendMSG
	if err:=json.Unmarshal(data["sendMSG"], &msg);err!=nil{
		fmt.Printf("json.Umarshal jsonStr failed, err:%v\n", err)
		return
	}
	fmt.Printf("msg:%v\n", msg)
}

在这里插入图片描述

总结

以上是golang对json的一些操作,经常用于服务器开发对json的处理中

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值