分享
  1. 首页
  2. 文章

用golang实现json序列化,避免输出null

悟道人 · · 4170 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近开发过程遇到一个go序列化的问题,
前端要求数据返回

{
 "user":"zhangsan",
 "role":[
 {"name":"管理员"},{"name":"观察者"}
 ]
}

go中的数据结构是这样的

type Role struct{
 Name string `json:"name"`
}
type Info {
 User string `json:"user"`
 Role []Role `json:"role"`
}
data,_:=json.Marshal(&info{User:"zhangsan"})
fmt.Println(string(data))

如果info.Role没有数据时,因为go的json标准库会将空切片、空指针返回null,实际返回给前端的数据是这样的

{
 "user":"zhangsan",
 "role":null
}

这个数据前端拿到后判断role的长度时就会出错,一般的做法是初始化切片Role

type Role struct{
 Name string `json:"name"`
}
type Info {
 User string `json:"user"`
 Role []Role `json:"role"`
}
data:=json.Marshal(&info{User:"zhangsan",Role:[]Role{}})
fmt.Println(string(data))

这样就可以按照协定的结构返回数据

{
 "user":"zhangsan",
 "role":[]
}

但是我们存在大量这样的代码,如果要都初始化一次,那简直是丧心病狂????,就像下面这样

type Info {
 User string `json:"user"`
 Role []Role 
 Cols1 []string
 Cols2 []string
 Cols3 []string
 Cols4 []string
 Cols5 []string
 Cols6 []string
 ...//不知道还有n多
}

网上找了一大圈也没找到有处理这种情况的办法,还是自己动手写了个简单的处理器

package binding
import (
 "reflect"
 "strconv"
 "strings"
)
type marshal struct {
}
//json反序列化
func Marshal(obj interface{}) string {
 v := reflect.ValueOf(obj)
 return new(marshal).parse(v)
}
//处理开始
func (this *marshal) parse(v reflect.Value) string {
 if v.Kind() == reflect.Ptr {
 v = v.Elem()
 }
 switch v.Kind() {
 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 return strconv.FormatInt(v.Int(), 10)
 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 return strconv.FormatUint(v.Uint(), 10)
 case reflect.Float32, reflect.Float64:
 return strconv.FormatFloat(v.Float(), 'f', -1, 64)
 case reflect.String:
 return `"` + v.String() + `"`
 case reflect.Bool:
 return strconv.FormatBool(v.Bool())
 case reflect.Struct:
 return this.parseStruct(v, v.Type())
 case reflect.Map:
 return this.parseMap(v, v.Type())
 case reflect.Slice:
 return this.parseSlice(v, v.Type())
 case reflect.Interface:
 return this.parse(reflect.ValueOf(v.Interface()))
 }
 return "null"
}
//处理结构体
func (this *marshal) parseStruct(v reflect.Value, t reflect.Type) string {
 if v.Kind() == reflect.Ptr {
 v = v.Elem()
 }
 if t.Kind() == reflect.Ptr {
 t = t.Elem()
 }
 var str = make([]string, t.NumField())
 for i := 0; i < t.NumField(); i++ {
 field := t.Field(i)
 value := v.Field(i)
 fieldName := field.Name
 tag := field.Tag.Get("json")
 if tag != "" {
 f := strings.Split(tag, ",")
 fieldName = f[0]
 }
 if fieldName == "-" {
 continue
 }
 str[i]= `"`+fieldName+`":`+this.parse(value)
 }
 return "{" + strings.Join(str, ",") + "}"
}
//处理切片
func (this *marshal) parseSlice(v reflect.Value, t reflect.Type) string {
 var str = make([]string, v.Len())
 for i := 0; i < v.Len(); i++ {
 str [i]= this.parse(v.Index(i))
 }
 return `[` + strings.Join(str, ",") + "]"
}
//处理map
func (this *marshal) parseMap(v reflect.Value, t reflect.Type) string {
 var str = make([]string, v.Len())
 m := v.MapRange()
 var i int
 for m.Next() {
 str[i]= `"`+m.Key().String()+`":`+this.parse(m.Value())
 i++
 }
 return "{" + strings.Join(str, ",") + "}"
}

使用方法

type Role struct {
 Name string `json:"name"`
}
type Info struct {
 Name string `json:"name"`
 Role []Role `json:"role"`
}
s := Marshal(Info{Name: "zhangsan"})
fmt.Println(s)

输出结果

{"name":"zhangsan","role":[]}

好用是好用,但是性能比标准库差了5倍,一般情况下也足够了????


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:悟道人

查看原文:用golang实现json序列化,避免输出null

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
4170 次点击
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏