相关文章推荐
豪气的感冒药  ·  javascript - ...·  1 年前    · 
近视的手套  ·  2018-10-28 ...·  1 年前    · 
mp.weixin.qq.com

现在开发API,所输出的基本上都是JSON格式的内容,相比比较旧的XML格式,JSON轻便、简洁、易于传输,所以现在的API使用非常多。

Gin对于API JSON的支持非常友好,可以让我们非常方便的开发一个基于JSON的API。

func main() {    r := gin.Default()    r.GET("/hello"func(c *gin.Context) {        c.JSON(200, gin.H{"message""hello world"})    })    r.Run(":8080")}复制代码

一个非常简单的例子,主要知识点在于 c.JSON 方法,它可以让我们非常方便的输出JSON格式的内容。

现在运行打开浏览器访问 http://localhost:8080/hello 可以看到如下内容:

{"message":"hello world"}复制代码

这是一个JSON格式的字符串,第三方调用者可以获得这个JSON内容,把它转换为一个JSON对象,然后通过 message 字段获取对应的值,也就是 hello world

这里我们使用了 gin.H 这个类型来构建了一个键值对对象,其实 gin.H 是一个 map[string]interface{}

// H is a shortcut for map[string]interface{}type H map[string]interface{}复制代码

gin.H 主要是为了帮助我们开发者很方便的构建出一个 map 对象,不止用于 c.JSON 方法,也可以用于其他场景。

Struct 转 JSON

c.JSON 方法非常强大,不止可以用于 map 的输出,还可以把我们自定义的对象 struct 转为一个json字符串输出。

func main() {    r := gin.Default()    r.GET("/users/123"func(c *gin.Context) {        c.JSON(200, user{ID: 123, Name: "张三", Age: 20})    })    r.Run(":8080")}type user struct {    ID   int    Name string    Age  int}复制代码

这个例子中我们自定义了一个 user struct 来表示用户,然后我们注册一个用户ID为123的路由,用于输出这个用户的信息,这里使用的就是 user struct,把它作为参数直接传给 c.JSON 方法即可。

现在我们运行,在浏览器里访问 http://localhost:8080/users/123 可以看到如下信息:

{"ID":123,"Name":"张三","Age":20}复制代码

完美、简单的把这个用户的信息作为一个JSON字符串输出。

自定义JSON字段名称

看上面的例子,我们发现输出的JSON字符串的字段和我们定义的 user 的字段名一样,但是这样的命名格式显然不太适合JSON,因为JSON的字段应该是小写字母开头的,这比较符合当前大家所遵守的JSON风格。

Gin是支持字段名字重新命名的,并且很简单,和Golang原生的JSON一样。

type user struct {    ID   int    `json:"id"`    Name string `json:"name"`    Age  int    `json:"age"`}复制代码

只需要在 user struct 定义的时候为字段添加 json tag 即可。关于 Struct Tag 的内容请参考我以前写的 《Go语言实战》笔记(二十五) | Go Struct Tag 这篇文章,这里不再赘述。

现在我们重新运行,在浏览器里访问 http://localhost:8080/users/123 ,发现看到的信息已经变了:

{"id":123,"name":"张三","age":20}复制代码

更符合JSON的风格了,看着更顺眼一些。

JSON数组

在一些情况下,比如我们需要获取所有用户信息,那么表达为JSON字符串来说,就是一个JSON数组。在Gin中,生成JSON数组也很简单,只要我们传递给 c.JSON 的参数是个数组就可以。

    allUsers := []user{{ID: 123, Name: "张三", Age: 20}, {ID: 456, Name: "李四", Age: 25}}    r.GET("/users", func(c *gin.Context) {        c.IndentedJSON(200, allUsers)    })复制代码

我们首先定义了一个 user 数组,然后使用 c.IndentedJSON 输出JSON字符串,现在运行打开浏览器,访问 http://localhost:8080/users 就可以看到如下信息,一个JSON数组字符串:

[    {        "id": 123,        "name""张三",        "age": 20    },    {        "id": 456,        "name""李四",        "age": 25    }]复制代码

IndentedJSON 美化

上面的例子,我们可以看到,输出的JSON字符串都是扁平的,没有缩进,不美观。对于这种情况,Gin也为我们提供了便捷的方法,让我们输出的JSON更好看。

    r.GET("/users/456"func(c *gin.Context) {        c.IndentedJSON(200, user{ID456, Name"李四", Age25})    })复制代码

想美化JSON的输出,使用 c.IndentedJSON 方法即可,现在现在我们运行访问 http://localhost:8080/users/456 就可以看到JSON已经被美化了,更容易看了。。

{    "id": 456,    "name": "李四",    "age": 25}复制代码

PureJSON

对于JSON字符串中特殊的字符串,比如 < ,Gin默认是转义的,比如变成 \ u003c ,但是有时候我们为了可读性,需要保持原来的字符,不进行转义,这时候我们就可以使用 PureJSON

    r.GET("/json"func(c *gin.Context) {        c.JSON(200, gin.H{            "message""<b>Hello, world!</b>",        })    })    r.GET("/pureJson"func(c *gin.Context) {        c.PureJSON(200, gin.H{            "message""<b>Hello, world!</b>",        })    })复制代码

用这两个API进行对比,我们运行访问 http://localhost:8080/json ,显示信息如下:

{"message":"\u003cb\u003eHello, world!\u003c/b\u003e"}复制代码

特殊字符已经被转义了,现在访问 http://localhost:8080/pureJson ,显示的就是原始信息:

{"message":"<b>Hello, world!</b>"}复制代码

可读性更强。

AsciiJSON

如果要把非 Ascii 字符串转为unicode编码,Gin同样提供了非常方便的方法。

    r.GET("/asciiJSON"func(c *gin.Context) {        c.AsciiJSON(200, gin.H{"message""hello 飞雪无情"})    })复制代码

通过 c.AsciiJSON 方法,Gin可以把所有的非 Ascii 字符全部转义为 unicode 编码,现在我们运行看看结果。

{"message":"hello \u98de\u96ea\u65e0\u60c5"}复制代码

飞雪无情 4个字已经被转义为 \u98de\u96ea\u65e0\u60c5 了,避免乱码。

加速JSON

在Gin中,提供了两种JSON解析器,用于生成JSON字符串。默认的是Golang(Go语言)内置的JSON,当然你也可以使用jsoniter,据说速度很快。如果要使用jsoniter,我们在 go build 编译的时候只需要这么做即可:

go build -tags=jsoniter .复制代码

这样我们就是用了jsoniter,是基于条件编译的技术,具体可以参考我这篇文章 Go语言中自动选择json解析库

关于Gin源代码如何实现自动选择JSON也大同小异,关于这个源代码分析,我会发到星球里,作为星球会员福利,大家可以扫文末的二维码加入。

Gin对于JSON的支持还是非常强大的,我们只需要用好这些方法,就可以高效的开发出我们的API。更多关于Gin的讨论可以加入我的星球 Golang Gin 实战 ,有更深入的讨论,一对一的答疑,公众号和博客没有的源代码分析。

精彩文章推荐

Golang Gin 实战(七)| 分组路由源代码分析

Golang Gin 实战(六)| 获取Form表单参数和原理分析

Golang Gin 实战(五)| 接收数组和map

Golang Gin 实战(四)| URL查询参数的获取和原理分析

Golang Gin 实战(三)| 路由参数

Golang Gin 实战(二)| 简便的Restful API 实现

Golang Gin 实战(一)| 快速安装入门

我有几个的Go语言交流微信群,可以扫码关注公众号 flysnow_org 或者网站 https://www.flysnow.org/,加我好友,我拉你进来。

分类:
后端
标签: