go json 自定义_Go 开发当中 JSON 使用技巧

点击上方蓝色“后端开发杂谈”关注我们, 专注于后端日常开发技术分享

JSON 常用技巧

  • 忽略 struct 空字段

忽略 struct 空字段, 使用 omitempty

type User struct {
    Email string `json:"email,omitempty"`
    Pwd  string `json:"pwd,omitempty"`
}
  • 临时粘合两个struct

type BlogPost struct {
    URL string `json:"url"`
}

type Analytics struct{
    Visitors int `json:"visitors"`
}

json.Marshal(struct {
    *BlogPost
    *Analytics
}{post, analytics})
  • 临时切开两个struct

json.Unmarshal([]byte(`{
    "url":"www@163.com",
    "visitors":10
}`), struct{
   *BlogPost
   *Analytics
}{&post, &analytics})
  • 临时改名 struct 的字段

type Cache struct {
    Key    string `json:"key"`
    MaxAge int    `json:"cacheAge"`
}

json.Marshal(struct {
    *Cache
    OmitMaxAge int `json:"cacheAge,omitempty"` // remove bad key
    MaxAge     int `json:"max_age"` // add new key
}{cache, 0, 10})
  • 使用字符串传递数字

type Object struct {
    Num int `json:"num,string"`
}

这个对应的json是 {"num":"100"}, 如果json是 {"num":100} 则会报错
  • 使用 MarshalJSON 支持 time.Time

go 默认会把time.Time用字符串方式序列化. 如果想用其他方式表示time.Time, 需要自定义类型并定义MarshalJSON

type timeImplMarshaler time.Time

func (o timeImplMarshaler) MarshalJSON() ([]byte, err) {
    seconds := time.Time(o).Unix()
    return []byte(strconv.FormatInt(seconds, 10)), nil
}
  • 使用 RegisterTypeEncoder 支持 time.Time

jsoniter 能够对不是自定义的 type 定义 JSON 编解码方式. 比如对于time.Time可以使用 epoch int64 序列化.

import "github.com/json-iterator/go/extra"

extra.RegisterTimeAsInt64Codec(time.Microsecond)
ouput, err := jsoniter.Marshal(time.Unix(1,1002))
should.Equal("1000001", string(output))
  • 使用MarshalText,UnmarshalText支持非字符串作为key的map

虽然 JSON 标准里只支持string作为keymap. 但是go通过MarshalText()接口, 使得其他类型也可以作为mapkey.

type Key struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

// 必须是传值调用(编码)
// 函数当中不能调用 json.Marshal() 函数
func (k Key) MarshalText() ([]byte, error) {
    data := fmt.Sprintf("%v_%v", k.Name, k.Value)
    return []byte(data), nil
}

// 必须是传指针调用(解码), 否则解析的值是空. 
// 函数当中不能调用 json.Unmarshal() 函数
func (k *Key) UnmarshalText(text []byte) (error) {
    tokens := strings.Split(string(text), "_")
    if len(tokens) == 2 {
        k.Name = tokens[0]
        k.Value = tokens[1]
        return nil
    }
    return errors.New("invalid text")
}

func main() {
    val := map[Key]string{{"12", "22"}: "2"}
    data, err := json.Marshal(val)
    fmt.Println(string(data), err)

    var vv map[Key]string
    json.Unmarshal(data, &vv)
    fmt.Println(vv)
}
  • 使用 json.RawMessage

如果部分 json 文档没有标准格式, 可以把原始的信息使用 []byte 保存下来.

type RawObject struct {
    Key string
    Raw json.RawMessage
}

func main() {
    var data RawObject
    json.Unmarshal([]byte(`{"key":"111", "raw":[1,2,3]}`), &data)
    fmt.Println(string(data.Raw)) // [1,2,3]
}
  • 使用 json.Number

默认情况下, 如果是interface对应数字的情况会是float64类型的. 如果输入的数字比较大, 这个会有损精度. 可以使用UseNumber()启用json.Number来用字符串表示数字.

  • 统一更改字段的命名风格

① 经常 JSON 里的字段名和 Go 里的字段名是不一样的. 可以使用field tag来修改.

② 但是一个个字段来设置, 太过于麻烦, 如果使用 jsoniter 可以统一设置命名风格.

按照 ①, ② 的方式去选择 JSON 的字段名. 如果方式 ① 的字段名存在, 则使用方式 ①, 否则再使用方式 ②

type T struct {
    UserName      string
    FirstLanguage string `json:"language"`
}

extra.SetNamingStrategy(func(s string) string {
    return strings.ToLower(s)
})

d, _ := jsoniter.Marshal(T{})
fmt.Println(string(d)) // {"username":"","language":""}
  • 支持私有的字段

Go 标准库只支持 public 的 field. jsoniter 额外支持了 private 的 field. 需要使用SupportPrivateFields()来开启.

struct {
extra.SupportPrivateFields()

24b383571c884dae47914140ff4a0c89.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值