美文网首页
Go语言里的Json

Go语言里的Json

作者: FunFeast | 来源:发表于2017-08-03 22:00 被阅读1446次

Json是一种轻量级数据交换格式,具有灵活、易于阅读的特点,在互联网行业有广泛的应用。Go语言运行时里自带了encoding/json包,提供了Marshal()和Unmarshal()两个函数进行编码和解码,两个函数原型如下:

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

废话少说,直接上例子:

package main

import (
    "fmt"
    "encoding/json"
)

type Foo struct {
    Name string
    Age  int
}

func main() {
    data := []byte(`{"Name": "John Doe", "Age": 25}`)
    var f Foo
    
    json.Unmarshal(data, &f)
    fmt.Printf("%s is %d years old.\n", f.Name, f.Age)

    output, _ := json.Marshal(&f)
    fmt.Println(string(output))
}

用法很简单,不过有两个问题需要说明一下:

  1. 结构体Foo里的字段必须是大写字母开头,否则将不能从Json中解析出对应的字段。原因是Go语言约定一个包中只有首字母大写的符号才被导出给其他包使用。json.Unmarshal()函数是在另外一个包里的,所以如果字段名小写,就无法进行赋值。

  2. 这种写法默认把Json里的字段赋值给结构体Foo里的同名字段,但是两者的字段名并不总是能保持一致,比如Json里的字段名可能是小写的name和age。这种情况下就需要手动指定字段的对应关系:

     type Foo struct {
         Name string `json:"name"`
         Age  int    `json:"value"`
     }
    

结构体Foo里的字段不但可以是基本类型,也可以是其他的结构体,比如下面这个例子:

type Employment struct {
    Company  string `json:"company"`
    Title    string `json:"title"`
}

type Foo struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
    Job  Employment `json:"job"`
}

func main() {
    data := []byte(`{"name": "John Doe", "age": 25, "job": {"company": "ABC", "title": "Engineer"}}`)
    var f Foo
    
    json.Unmarshal(data, &f)
    fmt.Printf("%s is %d years old.\n", f.Name, f.Age)

    output, _ := json.Marshal(&f)
    fmt.Println(string(output))
}

前面这两个例子里,Json的结构都是已经确定了的,因此才可以预先定义好结构体,然后用Marshal()和Unmarshal()在Go对象和Json串之间进行转换。有时候在解析之前我们可能并不知道Json对象里有哪些字段,这就需要一种更灵活的处理方式。在Python里,json.loads()直接将Json串转换成字典。类似的,在Go语言里,可以用把字段不确定的Json串转换成map。看下面这个例子:

type Foo struct {
    Name  string                 `json:"name"`
    Age   int                    `json:"age"`
    Job   Employment             `json:"job"`
    Extra map[string]interface{} `json:"extra"`
}

func main() {
    data := []byte(`{
        "name": "John Doe",
        "age": 25,
        "job": {
            "company": "ABC",
            "title": "Engineer"
        }, 
        "extra": {
            "marital status": "married",
            "childrens": 0
        }}`)
    var f Foo

    json.Unmarshal(data, &f)
    fmt.Printf("%s is %d years old and works at %s.\n", f.Name, f.Age, f.Job.Company)
    fmt.Printf("He is %s and has %d childrens.\n", f.Extra["marital status"].(string), int(f.Extra["childrens"].(float64)))

    output, _ := json.Marshal(&f)
    fmt.Println(string(output))
}

Extra对应了Json对象里结构不确定的extra字段。Go语言的map在声明时必须指定key和value的类型(这点远不如Python灵活),但是extra里的字段可能是不同类型,因此这个例子里使用了interface作为value类型。interface也就是“接口”,Go语言里任何数据类型都是某种接口,因此interface类型可以指代任何类型。当然我们也可以自定义interface类型,这不在本文的讨论范围之内。按照我的理解,interface类型在这里的作用类似于C语言里的void *。

还有一点值得一提的是,例子里的childrens字段值虽然是整数,但是被解析成了float64类型。在Json的定义中,值的类型不分整型和浮点型,只有一个number类型,因此在我们没有指定字段和类型的情况下,Unmarshal()函数把所有number类型的值都当作float64。我也是在写这篇文章的时候才发现这一点的。

有了这些技巧,基本上已经能应付绝大部分的Json处理任务了。如果还是觉得不够好用,可以尝试一下bit.ly的simplejson,或者性能更好的easyjson

相关文章

  • Go语言里的Json

    Json是一种轻量级数据交换格式,具有灵活、易于阅读的特点,在互联网行业有广泛的应用。Go语言运行时里自带了enc...

  • [Go基础]Json在Go中的使用

    前言 本文主要根据Go语言Json包[1]、官方提供的Json and Go[2]和go-and-json[3]整...

  • Go语言:json转map

    使用go语言将json解析到map里,这里主要使用到encoding/json包下的Unmarshal()函数。函...

  • Go语言标准库之JSON编解码

    Go语言标准库之JSON编解码 基本的类型 Go语言中的数据类型和JSON的数据类型的关系 bool -> JSO...

  • Go语言标准库之JSON编解码

    Go语言标准库之JSON编解码 基本的类型 Go语言中的数据类型和JSON的数据类型的关系 bool -> JSO...

  • go json解析Marshal和Unmarshal

    go json解析Marshal和Unmarshal - Go语言中文网 - Golang中文社区

  • go操作json

    Go 语言提供了关于 json 的标准库包 encoding/json。 详细官网文档见 json package...

  • Go 对象扩展与Gorm JSON 时间格式化

    JSON 解析与扩展已有类型 Go 语言是没有完整的 OOP 对象模型的,在 Golang 的世界里没有继承,只有...

  • go语言json处理

    json是一种经常使用的数据格式,下面总结一下json的使用json与struct转换的话struct的属性必须首...

  • go 语言 string to json

    刚刚学习go,记录一下 By: single430

网友评论

      本文标题:Go语言里的Json

      本文链接:https://www.haomeiwen.com/subject/rkjmlxtx.html