欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Go语言的数据结构转JSON

程序员文章站 2022-06-15 15:45:44
目录结构体转为 json 格式接口转为 json 格式marshal() 函数的原型总结在日常工作中,除了需要从 json 转化为 go 的数据结构。但往往相反的情况是:我们需要将数据以 json 字...

在日常工作中,除了需要从 json 转化为 go 的数据结构。但往往相反的情况是:我们需要将数据以 json 字符串的形式发送到 web 服务器。今天我们将学会如何从一个结构化数据编码为 json 。

json(javascript object nanotation)是一种数据交换格式,常用于前后端数据传输。任意一端将数据转换成json 字符串,另一端再将该字符串解析成相应的数据结构,如string类型,strcut对象等。

结构体转为 json 格式

比如,我们有如下的结构体:

type student struct {
    name string
    age int
    address address
}

type address struct {
    road string
    street string
    city string
    province string
    country string
}

zhang3 := student{
        name: "张三",
        age:  18,
        address: address{
            road:     "renmin south road",
            street:   "123 street",
            city:     "cs",
            province: "hn",
            country:  "cn",
        },
    }

将学生编码为 json 格式,我们可以使用 json 包中的 json.marshl() 函数:

info_of_zhang3, err := json.marshal(zhang3)
if err == nil {
    fmt.println(string(info_of_zhang3))
} else {
    fmt.println(err)
    return
}

marshal() 函数返回编码后的 json (字节切片)和 error 信息(如果出错的话)。然后我们可以打印 json 字符串。
完整代码如下:

package main

import (
    "encoding/json"
    "fmt"
)

type student struct {
    name    string
    age     int
    address address
}

type address struct {
    road     string
    street   string
    city     string
    province string
    country  string
}

func main() {

    zhang3 := student{
        name: "张三",
        age:  18,
        address: address{
            road:     "renmin south road",
            street:   "123 street",
            city:     "cs",
            province: "hn",
            country:  "cn",
        },
    }

    info_of_zhang3, err := json.marshal(zhang3)
    if err == nil {
        fmt.println(string(info_of_zhang3))
    } else {
        fmt.println(err)
        return
    }

}

运行代码,得到如下 json 数据结果:

$ go run main.go
{"name":"张三","age":18,"address":{"road":"renmin south road","street":"123 street","city":"cs","province":"hn","country":"cn"}}

当你看 json 输出时,你可能已经注意到没有缩进。如果你想缩进输出并很好地格式化它,你可以使用json. marshalindent()函数。
比如,使用如下语句:

info_of_zhang3, err := json.marshalindent(zhang3, "", "    ")

函数解析:第二个参数指定每行输出的开头的字符串。输出的开头,第三个参数指定每行要缩进的字符串。此时json.marshalindent(zhang3, "", "    ")可以得到如下的输出:

{
    "name": "张三",
    "age": 18,
    "address": {
        "road": "renmin south road",
        "street": "123 street",
        "city": "cs",
        "province": "hn",
        "country": "cn"
    }
}

接口转为 json 格式

有时您并不希望固定结构中的字段数量。 相反,您希望能够在需要的时候添加额外的数据。您可以使用空接口来实现这一点,如下所示:

type student map[string] interface{}
type address map[string] interface{}

使用空接口,可以创建自己的 student 变量,还可以添加想要的元素,就像这样:

zhang3 := student{
    "name": "张三",
    "age": 18,
    "address": address{
        "road": "renmin south road",
        "street": "123 street",
        "city": "cs",
        "province": "hn",
        "country": "cn",
    },
    "year": 2022,    // 新增学年
}

完整代码如下:

package main

import (
    "encoding/json"
    "fmt"
)

type student map[string]interface{}
type address map[string]interface{}

func main() {
    zhang3 := student{
        "name": "张三",
        "age":  18,
        "address": address{
            "road":     "renmin south road",
            "street":   "123 street",
            "city":     "cs",
            "province": "hn",
            "country":  "cn",
        },
        "year":       2022, // 新增学年
        "graduateat": 2026, // 毕业年份
    }

    infoofzhang3, err := json.marshalindent(zhang3, "", "    ")
    if err == nil {
        fmt.println(string(infoofzhang3))
    } else {
        fmt.println(err)
    }
}

代码输出结果为:

{
    "address": {
        "city": "cs",
        "country": "cn",
        "province": "hn",
        "road": "renmin south road",
        "street": "123 street"
    },
    "age": 18,
    "graduateat": 2026,
    "name": "张三",
    "year": 2022
}

同时我们能看到输出的 json 中的键的顺序是按字母排序的。

marshal() 函数的原型

我们看一下 marshal 函数:

func marshal(v interface{}) ([]byte, error) {
   e := newencodestate()

   err := e.marshal(v, encopts{escapehtml: true})
   if err != nil {
      return nil, err
   }
   buf := append([]byte(nil), e.bytes()...)

   e.reset()
   encodestatepool.put(e)

   return buf, nil
}

函数可以接收任意类型的接口数据 v,并转换为字节数组类型,返回值就是 json 数据和错误信息;若转换成功,则 err == nil;
在进行对象转换为json的过程中,会遵循一下几条原则:
a. 布尔型转换为json后仍然是布尔型;
b. 浮点型转换为json后里面的常规数字;
c. 字符串将以 utf-8 编码转化输出为 unicode 字符串,将特殊字符转义;
d. 数组和切片被转换为json里面的数组,[]byte类会被转换为 base64 编码后的字符串,slice的零值被转换为null;
e. 结构体转换为 json 对象,并且只有结构体内变量必须首字母大写,才可被导出的字段转化输出,而且这些字段会被作为 json 对象的字符串索引;
f. 转换一个 map 类型的数据结构时,该数据的类型必须时 map[string]t ,t 可以是encoding/json 包支持的任意类型。

总结

本文只是简单的把 go 语言常见的结构体和接口转化为 json 数据,其他类型类似,最后给出了编码的函数 marshal() 原型, 并简单进行了解释。

除此之外,encoding/json 包还提供了 encode() 和 decode() 函数用于单一对象的格式转化,而 marshal() 和 unmarshal() 函数工作于多个对象和字节流上。

其实,本文只是简单的介绍了 go 语言和 json 数据在控制台的简单转化,等后续的文章介绍了文件读取和写入时,就可以学会与 json 文件打交道了。敬请期待!

到此这篇关于go 转 json的文章就介绍到这了,更多相关go 转 json内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关标签: Go JSON