示例:go语言将结构体的数据保存为JSON格式的文本数据

内容摘录自《go语言从入门到进阶实战》
JSON格式是一种用途广泛的对象文本格式。在Go语言中,结构体可以通过系统提供的json.Marshal()函数进行序列化。为了演示怎样通过反射获取结构体成员及各种值的过程,下面使用反射将结构体序列化为文本数据。

1.数据结构及入口函数 将结构体序列化为JSON的步骤如下:
(1)准备数据结构体。
(2)准备要序列化的结构体数据。
(3)调用序列化函数。

代码:

package main
import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"strconv"
)

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
	}
}

// 将任意值转换为json并输出到缓冲
func writeAny(buff *bytes.Buffer, value reflect.Value) error {

	switch value.Kind() {
	case reflect.String:
		// 写入带有双引号括起来的字符串
		buff.WriteString(strconv.Quote(value.String()))
	case reflect.Int:
		// 将整形转换为字符串并写入缓冲
		buff.WriteString(strconv.FormatInt(value.Int(), 10))
	case reflect.Slice:
		return writeSlice(buff, value)
	case reflect.Struct:
		return writeStruct(buff, value)
	default:
		// 遇到不认识的种类,返回错误
		return errors.New("unsupport kind: " + value.Kind().String())
	}

	return nil
}

// 将切片转换为json并输出到缓冲
func writeSlice(buff *bytes.Buffer, value reflect.Value) error {

	// 写入切片开始标记
	buff.WriteString("[")

	// 遍历每个切片元素
	for s := 0; s < value.Len(); s++ {
		sliceValue := value.Index(s)

		// 写入每个切片元素
		writeAny(buff, sliceValue)

		// 写入每个元素尾部逗号,最后一个字段不添加
		if s < value.Len()-1 {
			buff.WriteString(",")
		}
	}

	// 写入切片结束标记
	buff.WriteString("]")

	return nil
}

// 将结构体序列化为json并输出到缓冲
func writeStruct(buff *bytes.Buffer, value reflect.Value) error {

	// 取值的类型对象
	valueType := value.Type()

	// 写入结构体左大括号
	buff.WriteString("{")

	// 遍历结构体的所有值
	for i := 0; i < value.NumField(); i++ {

		// 获取每个字段的字段值(reflect.Value)
		fieldValue := value.Field(i)

		// 获取每个字段的类型(reflect.StructField)
		fieldType := valueType.Field(i)

		// 写入字段名左双引号
		buff.WriteString("\"")

		// 写入字段名
		buff.WriteString(fieldType.Name)

		// 写入字段名右双引号和冒号
		buff.WriteString("\":")

		// 写入每个字段值
		writeAny(buff, fieldValue)

		// 写入每个字段尾部逗号,最后一个字段不添加
		if i < value.NumField()-1 {
			buff.WriteString(",")
		}
	}

	// 写入结构体右大括号
	buff.WriteString("}")

	return nil
}
func main() {

	// 声明技能结构
	type Skill struct {
		Name  string
		Level int
	}

	// 声明角色结构
	type Actor struct {
		Name string
		Age  int

		Skills []Skill
	}

	// 填充基本角色数据
	a := Actor{
		Name: "cow boy",
		Age:  37,

		Skills: []Skill{
			{Name: "Roll and roll", Level: 1},
			{Name: "Flash your dog eye", Level: 2},
			{Name: "Time to have Lunch", Level: 3},
		},
	}

	if result, err := MarshalJson(a); err == nil {
		fmt.Println(result)
	} else {
		fmt.Println(err)
	}
}


你可能感兴趣的:(go,json,golang,数据结构)