写在前面
在上一篇文章《Golang中的读写数据(中)》中,我们学习了在Golang中如何读取命令行参数,接下来我们将学习Golang中的数据格式化。
我们都知道数据要在网络当中进行传输,或者是将其保存到文件当中,就要必须对其编码和解码。常见的编码格式有JSON和XML等。
一些概念的补充
编码: 从特定数据结构到数据流这一过程
解码: 解码是编码的逆过程,即从数据流到数据结构这一过程
序列化: 将内存当中的数据抓换成指定的格式的过程,例如将一个Java对象转为一个字符串
接下来我们将介绍在Golang中将数据编码为JSON的相关内容,在这一部分内容当中,我们将使用到encoding
这个库
JSON数据操作
为了演示这一部分的内容,我将之前我们学习结构体时用到的结构体抄写在下面
// 修仙者
type Immortal struct {
Name string
Age int
Gender string
}
复制代码
然后大家请看下面这个例子:
package main
import (
"encoding/json"
"fmt"
)
// 修仙者
type Immortal struct {
Name string
Age int
Gender string
}
func main() {
immortal := &Immortal{
Name: "韩立",
Age: 18,
Gender: "男性",
}
// 将修仙者韩立编码为json的[]byte
jsonByteImmortal, _ := json.Marshal(immortal)
fmt.Printf("%s\n", jsonByteImmortal)
}
复制代码
输出:
{"Name":"韩立","Age":18,"Gender":"男性"}
复制代码
上面用到的json.Marshal
函数的函数签名是func Marshal(v interface{}) ([]byte, error)
它返回的是byte数组,因此打印时需要指定格式。
JSON 与 Go 类型对应如下:
- bool 对应 JSON 的 boolean
- float64 对应 JSON 的 number
- string 对应 JSON 的 string
- nil 对应 JSON 的 null
不是所有的数据都可以编码为 JSON 类型:只有验证通过的数据结构才能被编码:
- JSON 对象只支持字符串类型的 key;要编码一个 Go map 类型,map 必须是 map[string]T(T是
json
包中支持的任何类型) - Channel,复杂类型和函数类型不能被编码
- 不支持循环数据结构;它将引起序列化进入一个无限循环
- 指针可以被编码,实际上是对指针指向的值进行编码(或者指针是 nil)
反序列化操作
在Golang中如何将一个JSON转换为Golang中的数据结构呢?
请看下面的例子:
package main
import (
"encoding/json"
"fmt"
)
// 修仙者
type Immortal struct {
Name string
Age int
Gender string
}
func main() {
immortal := &Immortal{
Name: "韩立",
Age: 18,
Gender: "男性",
}
jsonImmortal, _ := json.Marshal(immortal)
fmt.Printf("%s\n", jsonImmortal)
// 1. 事先知道json对应的数据类型时
var jsonValue Immortal
json.Unmarshal(jsonImmortal, &jsonValue)
fmt.Println("name",jsonValue.Name)
fmt.Println("age",jsonValue.Age)
fmt.Println("gender",jsonValue.Gender)
// 2. 不知道json对应的数据结构
var m interface{}
json.Unmarshal(jsonImmortal,&m)
jsonMap := m.(map[string]interface{})
for key, value := range jsonMap {
printJson(key,value)
}
}
func printJson(key string, value interface{}) {
switch value.(type) {
case string:
fmt.Println(key,"value is a string: ",value)
case float64:
fmt.Println(key,"value is int type: ",value)
case []interface{}:
fmt.Println(key,"value is a array",value)
case map[string]interface{}:
m:= value.(map[string]interface{})
for k, v := range m {
printJson(k,v)
}
}
}
复制代码
输出:
{"Name":"韩立","Age":18,"Gender":"男性"}
name 韩立
age 18
gender 男性
Name value is a string: 韩立
Age value is int type: 18
Gender value is a string: 男性
复制代码
在这个例子当中,存在着两种情况:
第一种情况:我们事先知道JSON数据对应的数据结构,则调用json.Unmarshal
函数将其解码(也可以理解为反序列化)并存入该数据结构指针变量指向的内存地址当中;
第二种情况:我们事先不知道JSON数据对应的数据结构,则可以使用类型断言技术得到JSON数据当中key: value
对应的值。
解码以及编码JSON数据流
json 包提供 Decoder 和 Encoder 类型来支持常用 JSON 数据流读写。NewDecoder 和 NewEncoder 函数分别封装了 io.Reader 和 io.Writer 接口。
func NewDecoder(r io.Reader) *Decoderfunc NewEncoder(w io.Writer) *Encoder
复制代码
要想把 JSON 直接写入文件,可以使用 json.NewEncoder 初始化文件(或者任何实现 io.Writer 的类型),并调用 Encode();反过来与其对应的是使用 json.NewDecoder 和 Decode() 函数:
func NewDecoder(r io.Reader) *Decoderfunc (dec *Decoder) Decode(v interface{}) error
复制代码
写在最后
在Golang中解析转换JSON数据的内容我们就简单介绍到这里。本文当中涉及到的例子可以点击此处下载。如果我的学习笔记能够给你带来帮助,还请多多点赞鼓励。文章如有错漏之处还请各位小伙伴帮忙斧正。
在下一篇文章当中,我们将一起来学习Golang当中一种独有的编码格式Gob
近期评论