Marshal
一、功能介绍
- 实现官方encoding/json包的marshal功能的简化版,实现将结构体转化为json格式字符流
- 支持int、string、struct、interface、ptr、map形式的数据类型
- 支持tag标签来实现字段重命名以及字段忽略的功能
- 支持非struct的部分数据类型(数据类型同上)转换(是因为函数的参数使用的interface的空接口,所以任何数据类型都会满足空接口条件,但是只实现了上述数据类型的marshal功能
//支持tag标签:
`json:"name"` //重命名字段
`-` //在转换中忽略该字段
//注:本marshal函数根据官方marshal的功能要求实现,首字母小写的字段会被自动忽略,要实现小写命名,请使用tag标签重命名字段方法
二、简单使用案例
在测例中我们测试下对一个含有int、string、array、map、ptr类型数据的struct进行marshal,同时测试了tag字段的省略以及重命名功能
- 首先定义结构体:同时给部分字段加上tag标签,测试tag标签的省略和重命名
type ColorGroup struct {
ID int
ID2 int `json:"-"`
IDptr *int
Name string `json:"type"`
Colors []string
IDs []int
Map map[string]string
}
- 之后实例化结构体,并调用我们的Marshal函数
group := ColorGroup{
ID: 1,
ID2: 3,
IDptr: &i,
Name: "Reds",
Colors: []string{
"Crimson", "Red", "Ruby", "Maroon"},
IDs: []int{
6, 7, 8},
Map: map[string]string{
"sadf": "mike", "asdf": "yoyo", "asdfasdgtqerw": "asdfasdrteqwt"},
}
c, err2 := marshal.Marshal(group)
- 运行结果:
- ID2被成功忽略,Name被成功改名为type,说明tag正确,
- 其余数据格式均与官方marshal输出相同;
完整案例代码:
package main
import (
marshal "Marshal"
"encoding/json"
"fmt"
"os"
)
func main() {
type ColorGroup struct {
ID int
ID2 int `json:"-"`
IDptr *int
Name string `json:"type"`
Colors []string
IDs []int
Map map[string]string
}
var i int
i = 2
group := ColorGroup{
ID: 1,
ID2: 3,
IDptr: &i,
Name: "Reds",
Colors: []string{
"Crimson", "Red", "Ruby", "Maroon"},
IDs: []int{
6, 7, 8},
Map: map[string]string{
"sadf": "mike", "asdf": "yoyo", "asdfasdgtqerw": "asdfasdrteqwt"},
}
c, err2 := marshal.Marshal(group)
if err2 != nil {
fmt.Println("error:", err2)
}
os.Stdout.Write(c)
fmt.Println("")
}
三、程序实现
3.1 datavbuf 结构体
用来存储marshal返回的json格式字符流
type datavbuf struct {
bytes.Buffer
}
3.2 (buf *datavbuf)Marshal
结构体函数,使用reflect映射接口数据,并调用marshal函数来判断数据类型,并调用处理对应数据类型的函数
func (buf *datavbuf) Marshal(v interface{
}) error {
val := reflect.ValueOf(v)
return buf.marshal(val)
}
3.3 (buf *datavbuf)marshal
根据Kind的类型调用对应的数据处理函数
func (buf *datavbuf) marshal(val reflect.Value) error {
switch val.Kind() {
case reflect.Int:
return buf.DealInt(val)
case reflect.String:
return buf.DealString(val)
case reflect.Slice:
return buf.DealSlice(val)
case reflect.Array:
return buf.DealArray(val)
case reflect.Map:
return buf.DealMap(val)
case reflect.Struct:
return buf.DealStruct(val)
case reflect.Ptr, reflect.Interface:
return buf.DealInterface(val)
default:
return errors.New("Wrong DataType: " + val.Kind().String())
}
}
3.4 DealInt
int类型数据处理函数,将数据按照json的格式加入字符流中
func (buf *datavbuf) DealInt(val reflect.Value) error {
if _, err := buf.Write(strconv.AppendInt([]byte{
}, val.Int(), 10)); err != nil {
return err
}
return nil
}
3.5 DealString
String类型数据处理函数,将数据按照json的格式加入字符流中,string前后要加入’ " ’
func (buf *datavbuf) DealString(val reflect.Value) error {
if err := buf.WriteByte('"'); err != nil {
return err
}
if _, err := buf.Write([]byte(val.String())); err != nil {
return err
}
if err := buf.WriteByte('"'); err != nil {
return err
}
return nil