Golang中的自定义json序列化

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

后端开发人员跟前端对接接口的时候,或多或少都会面临一些沟通问题,比如说枚举字符的定义,比如有整形状态字段:state

1: 成功
2: 失败
3: 处理中

通常给前端的时候,前段要做的是将1,2,3以及对应的中文释义存储为key/value的形式,key与value单看都无法知道对方的语义,
比如我只知道状态值为“1”, 是无法将其与“成功”对应起来的(当然这套状态的设计者肯定是知道的),后端通常给到前端的restful api
接口定义也是key/value的形式,这乍一看其实也没啥毛病,只要有key/value也没问题,后端定义通常会是

type MyResponse struct {
    ID    int64   `json:"id"`
    State int     `json:"state"`
}

但数字的表现形式终归是不不太明确的,如果对状态的定义换成以下形式:

Success: 成功
Fail: 失败
Pending: 处理中

基本可以理解为中英文互译了,理解起来也会更清晰一些不是,如果这么做的话,后端给到前端的响应字段状态的类型就需要修改成字符器格式

type MyResponse struct {
    ID    int64  `json:"id"`
    State string `json:"state"`
}

后端还是要做一层字符串到整型的转换,从目的来讲,我们只是想返给前端的state字段是字符串而已,也就是在做json序列化的时候将整型与字符串做一层转换,有更优雅的做法如下所示

type MyState int

func (u MyState) MarshalJSON() ([]byte, error) {
    var buf bytes.Buffer
    switch u {
    case 1:
        _, err := buf.WriteString(`"Success"`)
        return buf.Bytes(), err
    case 2:
        _, err := buf.WriteString(`"Fail"`)
        return buf.Bytes(), err
    case 3:
        _, err := buf.WriteString(`"Pending"`)
        return buf.Bytes(), err
    }

    return nil, fmt.Errorf("unsupported value: %v!", u)
}

只需要做两件事,自定义类型MyState,实现MarshalJSON方法

// Marshaler is the interface implemented by types that
// can marshal themselves into valid JSON.
type Marshaler interface {
    MarshalJSON() ([]byte, error)
}

只要类型实现了MarshalJSON方法,在json序列化时就会调用此方法,如此一来,我们就轻松实现了自定义json序列化,反序列化同样如此

// Unmarshaler is the interface implemented by types
// that can unmarshal a JSON description of themselves.
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
//
// By convention, to approximate the behavior of Unmarshal itself,
// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
type Unmarshaler interface {
    UnmarshalJSON([]byte) error
}

实现起来也很简单

func (u *MyState) UnmarshalJSON(data []byte) error {
    switch string(data) {
    case `"Success"`:
        *u = 1
        return nil
    case `"Fail"`:
        *u = 2
        return nil
    case `"Pending"`:
        *u = 3
        return nil
    }
    return fmt.Errorf("unsupported value: %v!", *u)
}

需要注意的是,UnmarshalJSON方法操作过程需要给receiver也就是u赋值,所以必须是指针类型,同样的,在实现
MarshalJSON方法,receiver的类型需要与结构体定义中的类型保持一致,否则自定义序列化会失败

参考:


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

本文来自:简书

感谢作者:wu_sphinx

查看原文:Golang中的自定义json序列化

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

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