最新消息:yaf表单扩展中新增加了浮点数、日期和集合的校验。php yaf框架扩展实践三——表单

golang中json编码和解码

Golang 1041浏览 0评论

json数据格式是目前世界上使用很广的一种数据格式之一,目前很多应用之间的交互都是使用json格式,最常见的如开发APP的时候,接口返回的数据一般都是json格式。

golang官方也提供了标准库对json格式的数据进行解码和编码,依据json数据标准规范4627版(RFC 4627),说起规范这种东西,真的要感觉这些大佬们,因为规范制定后,全球都按照这种规范来做,省去了不少的交流沟通成本。

golang中对json数据的处理主要使用encoding/json包,其中最常用的函数一个是Marshal——用来编码,一个是Unmarshal——用来解码,先看看json字符串的解码。

Unmarshal解码

先看下Unmarshal函数的原型:

func Unmarshal(data []byte, v interface{}) error
package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // json格式字符串
    var jsonUsers = []byte(`[
        {"id": "1", "name": "Anny"},
        {"id": "2", "name": "Tom"}
    ]`)

    // 用结构体User进行接收
    // Id属性后的``内的内容表示转化json数据时的一个设定
    // 例如:`json:"id,string"`,表示对应的json格式字符串键值为id,类型为字符串
    // `json:"name"`,表示对应的json格式字符串键值为name
    type User struct {
        Id   int    `json:"id,string"`
        Name string `json:"name"`
    }

    // 因为json格式字符串是个数组格式,这里也要定义数组
    var users []User
    err := json.Unmarshal(jsonUsers, &users)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", users)
    // output: [{Id:1 Name:Anny} {Id:2 Name:Tom}]
}

代码注释比较详细,不再多说明了,值得一提的是结构体的标签(Tag)内容,设计非常巧妙,可以查看以前写的这篇文章:golang中struct成员变量的标签(Tag)说明和获取方式。

另外查看Unmarshal这个函数,可以看到存储解析内容的变量类型是interface,也就说除了结构体外也可以使用其它类型进行接收,这里用字典(map)写了一个示例。

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // json格式字符串
    var jsonUsers = []byte(`[
        {"id": "1", "name": "Anny"},
        {"id": "2", "name": "Tom"}
    ]`)

    // 尝试用字典进行接收
    // 因为json格式的键通常为字符串类型
    // 值有可能为各种类型,如果整形、浮点、数组、对象等
    // 所以map存储的值定义为interface{}类型
    var users []map[string]interface{}
    err := json.Unmarshal(jsonUsers, &users)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", users)
    // output: [map[id:1 name:Anny] map[id:2 name:Tom]]
}

其实自己觉得用字典(map)来接收后续的流程不太好处理,如果要使用字典值(interface{})则需要对类型进行逐一判断,形如:

switch t := v.(type) {
case bool:
case int:
default:
}

接下来看下编码吧。

Marshal编码

func Marshal(v interface{}) ([]byte, error)

先看下从struct类型编码成json格式字符串的示例

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // 声明一个结构体
    type ColorGroup struct {
        ID     int      `json:"id,string"`
        Name   string   `json:"name,omitempty"`
        Colors []string `json:"colors"`
    }

    // 对ColorGroup类型的变量进行编码
    group := ColorGroup{
        ID:     1,
        Name:   "Reds",
        Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
    }
    b, err := json.Marshal(group)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
    // output: {"id":"1","name":"Reds","colors":["Crimson","Red","Ruby","Maroon"]}

    // 如果没有设置Name属性值,因为标记为了omitempty属性,则在编码成json的时候会忽略Name属性
    group = ColorGroup{
        ID:     1,
        Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
    }
    b, err = json.Marshal(group)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
    // output: {"id":"1","colors":["Crimson","Red","Ruby","Maroon"]}

    // 如果没有设置Colors值,因为没有omitempty属性,会输出nil
    group = ColorGroup{
        ID:   1,
        Name: "Reds",
    }
    b, err = json.Marshal(group)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
    // output: {"id":"1","name":"Reds","colors":null}

}

同解码一样,也可以将map类型进行编码。

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    m := map[string]interface{}{
        "id":      1,
        "name":    "Socrates",
        "friends": []string{"Plato", "Aristotle"},
    }
    b, err := json.Marshal(m)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
}

在实际开的时候,对map类型进行编码自己比较常用,通常用来api接口的数据输出。因为外围不需要再处理什么东西了,获取数据的函数会直接返回map[string]interface{}类型的数据,只需要json编码一下输出就可以了,处理起来就简单很多。

转载请注明:快乐编程 » golang中json编码和解码

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址