搜索
简帛阁>技术文章>golang json库的使用

golang json库的使用

文章目录

      • json库基本介绍
      • 序列化与反序列化
      • tag的使用
          • 别名
          • omitempty 字段可空
      • 时间相关的问题
          • 问题描述
          • 解决方案

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"`
}
文章目录json基本介绍序列化与反序列化tag使用别名omitempty字段可空时间相关问题问题描述解决方案json基本介绍对象在网络中是通过字节数组来进行传递,在日常前后端交互中,有可能
目录JSON:创建格式:基本数据类型序列化:map序列化:切片序列化:反序列化为结构体:反序列化为map:反序列化为切片:JSONJSON(JavaScriptObjectNotation):是一种
前言有的时候上游传过来字段是string类型,但是我们却想用变成数字来使用。本来用一个json:",string"就可以支持了,如果不知道golang这些小技巧,就要大费周章了。参考文章:JS
目录前言funcUnmarshal普通JSONJSON内嵌普通JSONJSON内嵌数组JSONJSON内嵌具有动态KeyJSON总结前言工作中我们经常会遇到解码JSON格式数据,本文通过4个示例介
我就废话不多说了,大家还是直接看代码吧~packagemainimport("encoding/json""fmt")typeProjectstruct{Namestring`json:"name"`
痛点json是当前最常用数据传输格式之一,纯文本,容易使用,方便阅读,在通信过程中大量被使用。你是否遇到过json中某个字段填入某种类型都适合而陷入两难境地(例如:定义了一个port字段,你却不知道
xorm支持各种关系数据库,最近使用postgresql时,总是踩到一些坑,在此记录下解决方式。在使用postgresqlarray类型时,查询有点问题,xorm官方文档给出重写方式,但是不是很
需求和思路在一般小项目或者一个小软件,例如客户端之类小程序中,可能会需要数据持久化但是使用一般数据库(Mysql)之类不合适使用sqlite3这种嵌入式是个较好方法,但是Go语言中sq
录一、sturctjsontag使用1tag格式说明2具体使用格式说明二、源码角度设计处理过程1typeFields2encode三、总结一、sturctjsontag使用1tag格式说明st
本文主要给大家介绍是关于Golang解析json数据相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细介绍:使用Golang解析json数据,这种json格式是对象数组,官方文档