xutil今天分享的文章源自于开源项目jinzaigo/xutil的封装。在封装过程中,劲仔将实现原理以及相关实践思考,写成文章分享出来,从而汇总系列文章集合。PHP转Go我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化
xutil 今天分享的文章源自于开源项目jinzaigo/xutil的封装。
在封装过程中,劲仔将实现原理以及相关实践思考,写成文章分享出来,从而汇总系列文章集合。
PHP转Go 我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大程度的减低了程序的复杂度。
反观go使用标准库encoding/json,来做json解析就没有那么愉快了(只要数据类型定义不对,就很容易抛error)
JSON解析实践 案例:用go重构的服务,对接的上游还是php服务,这时php接口输出的json串为{"name":"AppleWatchS8","price":"3199"} ,其中price字段应该得为float类。
但由于php弱类型语言,没有强制约束输出类型的机制,就很容易出现这种输出类型不对的情况,然后到go服务里得怎么处理呢?
标准库encoding/json 复制 package main
import (
"encoding/json"
"fmt"
)
type ProductInfo struct {
Name string `json: "name" `
Price float32 `json: "price" `
}
func main( ) {
str : = "{" name":" AppleWatchS8"," price":" 3199 "}"
data : = ProductInfo{ }
if err : = json.Unmarshal ( [ ] byte( str) , & data) ; err != nil {
fmt.Println ( "error: " + err.Error ( ) )
} else {
fmt.Println ( data)
}
}
// 输出结果
// error: json: cannot unmarshal string into Go struct field ProductInfo.price of type float32
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 显然,使用go标准库做json解析,是应对不了这种类型不一致的情况的。下面则借助第三方库的能力来做处理
第三方库json-iterator 简单介绍:
执行速度:jsoniter 的 Golang 版本可以比标准库(encoding/json)快 6 倍之多
两个特点:
完全兼容标准库,也就是API用法完全一样,原有逻辑代码不需要改动,只需要替换import包名 提供了一个PHP兼容模式,可以自动转换字符串/数字弱类型问题,可以将空数组[]转换为空结构体(解决PHP中的array输出为[]的问题)。注意,该兼容模式需要手动开启 安装方式:
复制 go get - u github.com / json- iterator/ go
具体代码实现:
复制 package main
import (
"fmt"
jsoniter "github.com/json-iterator/go"
"github.com/json-iterator/go/extra"
)
var json = jsoniter.ConfigCompatibleWithStandardLibrary
func init( ) {
extra.RegisterFuzzyDecoders ( ) // 开启PHP兼容模式
}
type ProductInfo struct {
Name string `json: "name" `
Price float32 `json: "price" `
}
func main( ) {
str : = "{" name":" AppleWatchS8"," price":" 3199 "}"
data : = ProductInfo{ }
if err : = json.Unmarshal ( [ ] byte( str) , & data) ; err != nil {
fmt.Println ( "error: " + err.Error ( ) )
} else {
fmt.Println ( data)
}
}
// 输出结果
// { AppleWatchS8 3199 }
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 看输出结果,会发现用了这个库并且开启了PHP兼容模式,json中price字段string类型,就会自动转换为结构体中定义的float32类型。
这样我们在使用price字段处理业务逻辑时,就只需要按float32做处理就行,不用进行类型断言。
这个库解决了json解析类型转换问题的同时,也能极大的提高我们开发效率。
收集到开源工具包xutil中 这个第三库用起来如此方便,那肯定是要收录进来的,将替换包名、手动开启PHP兼容模式、还有常用的API方法(系列化与反序列化操作),统一封装进来,简化使用流程。
同时,为了便于后续扩展更多的兼容模式,所以将代码都放在xjson目录下
以上这个思路也适用于大家封装自己内部使用的工具库。
使用示例:
go get -u github.com/jinzaigo/xutil之后,import github.com/jinzaigo/xutil/xjson,即可通过xjson.Unmarshal()等方法,进行json解析操作
示例代码:
复制 package main
import (
"fmt"
"github.com/jinzaigo/xutil/xjson"
)
type ProductInfo struct {
Name string `json: "name" `
Price float32 `json: "price" `
}
func main( ) {
str : = "{" name":" AppleWatchS8"," price":" 3199 "}"
data : = ProductInfo{ }
if err : = xjson.Unmarshal ( [ ] byte( str) , & data) ; err != nil {
fmt.Println ( "error: " + err.Error ( ) )
} else {
fmt.Println ( data)
}
}
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 总结 业务系统从php转go,或go对接php服务,都会遇到这个因为数据类型不一致导致json解析错误的共性问题。
使用第三方库json-iterator能很好的解决我们的痛点,并且比标准库执行速度还更快。
本文转载自微信公众号「 程序员升级打怪之旅」,作者「王中阳Go」,可以通过以下二维码关注。
转载本文请联系「 程序员升级打怪之旅」公众号。