golang json库的使用

json库基本介绍

对象在网络中是通过字节数组来进行传递的,在日常的前后端交互中,有可能会用到会有多种的形式,比如json,xml,pb等。这篇文章主要介绍一下golang语言中json相关库的日常用法

序列化与反序列化

序列化是指把内存中的对象转为字节数组的过程,方便在网络中传输,反序列化则相反,golang中涉及到的两个函数,包的位置:“encoding/json”

package json

// 序列化
func Marshal(v interface{}) ([]byte, error) {
}

// 反序列化
func Unmarshal(data []byte, v interface{}) error {
}

序列化传入对象,返回字节数组
反序列化传入字节数组和接收对象的地址,会自动填充对象

看一个例子:

type Student struct {
	Name string
	Age  uint32
}

func main() {
	stu := Student{
		Name: "james",
		Age:  22,
	}

	// marshal
	jsonObj, err := json.Marshal(stu)
	if err != nil {
		panic(err)
	}
	fmt.Printf("jsonObj : %s", jsonObj)

	str := `{"Name":"james","Age":22}`
	var stu2 Student

	// unmarshal
	err = json.Unmarshal([]byte(str), &stu2)
	if err != nil {
		panic(err)
	}
	fmt.Printf("stu2 : %+v\n", stu2)
}

运行结果:
在这里插入图片描述
注意: 这里有一个坑,golang的字段名必须大写开头,否则无法完成json的序列化,会丢失该字段。如果这里我们把Name小写,则无法完成映射

// 错误的写法,字段必须大写,保持为public
type Student struct {
	name string
	age  uint32
}

tag的使用

别名

通过上述的例子可以看到序列化后的字段名和golang的字段名是一样的,是大写的Name,有时前后端约定的json对象字段名并不相同,就需要通过tag完成映射

type Student struct {
	Name string `json:"name"`
	Age  uint32 `json:"age"`
}

这时返回的json对象就会以别名为准
在这里插入图片描述

omitempty 字段可空

使用该tag后,序列化时,当某个字段没有值(在golang中也就是为0值)时,会直接忽略该字段
看下区别,很容易理解:
为Age添加omitempty字段

type Student struct {
	Name string `json:"name"`
	Age  uint32 `json:"age,omitempty"`
}

将年龄设置为0值,或者不初始化

	stu := Student{
		Name: "james",
		Age:  0,
	}

看下marshal后的结果对比
添加omitempty:
在这里插入图片描述

未添加marshal:
在这里插入图片描述

注意:这里主要取决于协议需求

时间相关的问题

问题描述

当用户想要输入的时间为2006-01-02 15:04:05这种格式时,直接使用time.Time类型进行接收会遇到一个问题:cannot parse " 00:00:00"" as “T”

type XXXConfig struct {
	StartDate time.Time `json:"start_date"`
	EndDate   time.Time `json:"end_date"`
}

在这里插入图片描述

解决方案

因为golang的底层时间类型不一样导致的,需要重新定义别名,然后修改接口实现

const (
	YYYYMMDD          = "2006-01-02"
	DefaultTimeFormat = "2006-01-02 15:04:05"
)

// JSONTime is time
type JSONTime time.Time

// UnmarshalJSON for JSON Time
func (t *JSONTime) UnmarshalJSON(data []byte) (err error) {
	now, err := time.ParseInLocation(`"`+DefaultTimeFormat+`"`, string(data), time.Local)
	*t = JSONTime(now)
	return
}

// MarshalJSON for JSON Time
func (t JSONTime) MarshalJSON() ([]byte, error) {
	b := make([]byte, 0, len(DefaultTimeFormat)+2)
	b = append(b, '"')
	b = time.Time(t).AppendFormat(b, DefaultTimeFormat)
	b = append(b, '"')
	return b, nil
}

// String for JSON Time
func (t JSONTime) String() string {
	return time.Time(t).Format(DefaultTimeFormat)
}

这时,将结构体字段类型改变下为自己的定义的类型就解决了

type XXXConfig struct {
	StartDate JSONTime `json:"start_date"`
	EndDate   JSONTime `json:"end_date"`
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值