JSON是一种比较通用的对象文本格式。在Go语言中,结构体数据可以通过系统提示的json.Marshal()函数进行序列化。
下面本文就对序列化数据进行模拟
将结构体序列化为json分为如下几个步骤:
(1) 准备数据结构
(2) 准备要序列化的结构体数据
(3) 调用序列化函数
主函数入口
package main
import (
"fmt"
"reflect"
"bytes"
"strconv"
)
func main(){
//创建技能结构体
type Skill struct {
Name string
Level int
}
//创建角色结构体
type Actor struct {
Name string
Age int
Skills []Skill
}
//填充角色数据
a := Actor {
Name:"wangy"
Age:28
Skills: []Skill{{Name:"doctor",Level: 5},{Name: "student",Level: 5},{Name:"wife",Level: 5},},
}
if result, ok := MarshalJson(a); err==nil {
fmt.Println(result)
} else {
fmt.Println(err)
}
}
这里的MarshalJson()是自己创建的函数将Actor实例化结构体转化成JSON格式,如果转化成功则输出数据,失败则打印错误。
MarshalJson()函数是序列化过程的主函数入口。通过这个函数可以调用不同的子序列化函数满足不同类型数据的转化。该函数传入一个interface{}类型数据,如果转化成功返回数据,失败则返回错误信息。
JSON系列化主函数代码:
func MarshalJson(v interface{}) (string, error) {
//准备一个缓冲
var b bytes.Buffer
//将任意值转化成json并写入缓冲中
if err := WriteAny(&b,reflect.ValueOf(v));err == nil {
return b.String(),nil
} else {
return "", err
}
}
这里首先创建一个缓冲通道b用来写入数据
WriteAny()是自己创建的函数可以做任意值序列化,如果发生错误则返回错误信息。
WriteAny函数代码如下
//将人任意值转化成json格式并写入通道中
func WriteAny(b *bytes.Buffer, value reflect.Value) error {
//用switch分支处理不同数据的格式转化
switch value.Kind() {
case reflect.String:
//向通道中写入带双引号的字符串
return b.WriteString(strconv.Quote(value.String()))
case reflect.Int:
//将整型转换成字符串并写入到缓冲中
return b.WriteString(strconv.FormatInt(value.Int(),10))
case reflect.Slice:
//写入切片类型数据
WriteSlice(b, value)
case reflect.Struct:
WriteStruct(b,value)
default:
//遇到不认识的类型返回错误信息
return errors.New("unspport kind"+value.Kind().String())
}
return nil
}
//对切片序列化代码如下
func WriteSlice(b *bytes.Buffer, value reflect.Value) error {
//写入切片开始标记
b,WriterString("[")
//遍历每个元素
for i := 0; i < value.Len(); i++ {
//获取切片元素
valueSlice := value.Field(i)
//写入每个切片
WriteAny(b,valueSlice)
//除去最后一个元素外每个元素末尾写入逗号
if i < value.Len()-1 {
b.WriteString(",")
}
}
//写入切片结束标志
b.WriteString("]")
return nil
}
结构体序列化代码如下
//将结构体转化成json格式并写入到通道中
func WriteStruct(b *bytes.Buffer, value reflect.Value) error {
//获取value类型
valueType := value.Type()
//写入结构体左大括号
b.WriteString("{")
//遍历结构体所有值
for i := 0; i < value.NumField(); i++ {
//获取每个结构体的字段值
FieldValue := value.Field(i)
//获取每个字段的类型
FieldType := valueType.Field(i)
//写入字段的左双引号
b.WriteString("/"")
//写入字段名字
b.WriteString(valueType.Name())
//写入字段的右双引号
b.WriteString("/":")
//写入每个字段值
WriteAny(b,FieldValue)
//每个字段后面跟一个逗号
if i < value.NumField()-1{
s.WriteString(",")
}
}
//写入结构体的右大括号
s.WriteStirng("}")
return nil
}