golang无需结构体类型安全的JSON处理与查询插件库jsonic的使用
Golang无需结构体类型安全的JSON处理与查询插件库jsonic的使用
JSONIC简介
Jsonic
是一个完整的JSON数据处理工具集,无需定义结构体即可安全地进行JSON嵌套查询。该库提供了强类型方法,无需编写额外代码即可获得所需结果。
安装
go get github.com/sinhashubham95/jsonic
查询路径理解
Jsonic
使用一种独特而简单的方式来查询JSON中的元素。考虑以下JSON示例:
{
"a": {
"x": "p",
"arr": [
{
"a": "b",
"c.d": {
"e": "f"
}
}
]
},
"c": "d",
"a.x": {
"y": "q"
},
"a.x.y": {
"z": "r"
}
}
查询路径解析示例:
路径 | 结果 | 说明 |
---|---|---|
a | {“x”: “p”, “arr”: [{ “a”: “b”, “c.d”: { “e”: “f” } }]} | 返回a的整个JSON树 |
a.x | p | 返回a.x的值 |
a.x.y | q | 返回a.x.y的值 |
a.x.y.z | r | 返回a.x.y.z的值 |
a.arr[0].a | b | 返回数组中第一个元素的a值 |
a.arr[0].c.d.e | f | 返回嵌套对象中的e值 |
使用方法
创建新实例
import (
"github.com/sinhashubham95/jsonic"
)
func New() {
json := "{\"naruto\": \"rocks\"}"
j, err := jsonic.New([]byte(json))
// 使用创建的实例执行任何操作
}
创建子实例
import (
"github.com/sinhashubham95/jsonic"
)
func Child() {
json := "{\"naruto\": \"rocks\"}"
j, err := jsonic.New([]byte(json))
if err != nil {
return
}
// 创建子实例
child, err := j.Child("naruto")
// 现在可以使用这个子实例进行查询
}
获取路径数据
import (
"github.com/sinhashubham95/jsonic"
)
func Get() {
json := "{\"naruto\": \"rocks\"}"
j, err := jsonic.New([]byte(json))
if err != nil {
return
}
// 获取数据
data, err := j.Get("naruto")
// data将是interface{}类型,值为"rocks"
}
获取类型化数据
import (
"github.com/sinhashubham95/jsonic"
)
type Detail struct {
Name string `json:"name"`
}
func GetTyped() {
json := "{\"characters\": [{\"name\": \"naruto\"}, {\"name\": \"boruto\"}]}"
j, err := jsonic.New([]byte(json))
if err != nil {
return
}
// 获取类型化数据
var data []Detail
err := j.GetTyped("characters", &data)
// data将包含2个元素,name分别为naruto和boruto
}
其他类型化工具方法
import (
"github.com/sinhashubham95/jsonic"
)
func OtherGetters(j *jsonic.Jsonic, path string) {
// 基本类型
i, err := j.GetInt(path) // int
i64, err := j.GetInt64(path) // int64
f, err := j.GetFloat(path) // float32
f64, err := j.GetFloat64(path) // float64
b, err := j.GetBool(path) // bool
s, err := j.GetString(path) // string
// 数组
a, err := j.GetArray(path) // []interface{}
iArr, err := j.GetIntArray(path) // []int
i64Arr, err := j.GetInt64Array(path) // []int64
fArr, err := j.GetFloatArray(path) // []float32
f64Arr, err := j.GetFloat64Array(path) // []float64
bArr, err := j.GetBoolArray(path) // []bool
sArr, err := j.GetStringArray(path) // []string
// 映射
m, err := j.GetMap(path) // map[string]interface{}
iMap, err := j.GetIntMap(path) // map[string]int
i64Map, err := j.GetInt64Map(path) // map[string]int64
fMap, err := j.GetFloatMap(path) // map[string]float32
f64Map, err := j.GetFloat64Map(path) // map[string]float64
bMap, err := j.GetBoolMap(path) // map[string]bool
sMap, err := j.GetStringMap(path) // map[string]string
}
完整示例
package main
import (
"fmt"
"github.com/sinhashubham95/jsonic"
)
func main() {
// 示例JSON数据
jsonData := `{
"user": {
"name": "John Doe",
"age": 30,
"address": {
"street": "123 Main St",
"city": "New York"
},
"hobbies": ["reading", "coding", "gaming"],
"scores": {
"math": 95,
"science": 88
}
}
}`
// 创建Jsonic实例
j, err := jsonic.New([]byte(jsonData))
if err != nil {
fmt.Println("创建Jsonic实例失败:", err)
return
}
// 获取用户名
name, err := j.GetString("user.name")
if err != nil {
fmt.Println("获取用户名失败:", err)
} else {
fmt.Println("用户名:", name)
}
// 获取年龄
age, err := j.GetInt("user.age")
if err != nil {
fmt.Println("获取年龄失败:", err)
} else {
fmt.Println("年龄:", age)
}
// 获取城市
city, err := j.GetString("user.address.city")
if err != nil {
fmt.Println("获取城市失败:", err)
} else {
fmt.Println("城市:", city)
}
// 获取爱好列表
hobbies, err := j.GetStringArray("user.hobbies")
if err != nil {
fmt.Println("获取爱好列表失败:", err)
} else {
fmt.Println("爱好:")
for i, hobby := range hobbies {
fmt.Printf(" %d. %s\n", i+1, hobby)
}
}
// 获取数学成绩
mathScore, err := j.GetInt("user.scores.math")
if err != nil {
fmt.Println("获取数学成绩失败:", err)
} else {
fmt.Println("数学成绩:", mathScore)
}
// 使用Child创建子实例
user, err := j.Child("user")
if err != nil {
fmt.Println("创建子实例失败:", err)
return
}
// 从子实例获取数据
street, err := user.GetString("address.street")
if err != nil {
fmt.Println("获取街道失败:", err)
} else {
fmt.Println("街道:", street)
}
// 使用GetTyped获取结构化数据
type Address struct {
Street string `json:"street"`
City string `json:"city"`
}
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"`
Hobbies []string `json:"hobbies"`
}
var userData User
err = j.GetTyped("user", &userData)
if err != nil {
fmt.Println("获取用户数据失败:", err)
} else {
fmt.Printf("用户数据: %+v\n", userData)
}
}
这个示例展示了如何使用jsonic库进行各种JSON查询操作,包括基本类型查询、数组查询、嵌套对象查询以及类型化数据获取。
更多关于golang无需结构体类型安全的JSON处理与查询插件库jsonic的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang无需结构体类型安全的JSON处理与查询插件库jsonic的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang中使用jsonic进行类型安全的JSON处理
jsonic是一个轻量级的Go语言库,它允许你在不需要定义结构体的情况下,以类型安全的方式处理JSON数据。这对于处理动态JSON数据或快速原型开发非常有用。
安装jsonic
go get github.com/minio/jsonic
基本用法
1. 解析JSON
package main
import (
"fmt"
"github.com/minio/jsonic"
)
func main() {
// JSON字符串
jsonStr := `{
"name": "John",
"age": 30,
"isActive": true,
"address": {
"street": "123 Main St",
"city": "New York"
},
"hobbies": ["reading", "swimming"]
}`
// 解析JSON
obj, err := jsonic.Parse([]byte(jsonStr))
if err != nil {
panic(err)
}
// 访问字段
name := obj.Get("name").String()
age := obj.Get("age").Int()
isActive := obj.Get("isActive").Bool()
fmt.Printf("Name: %s, Age: %d, Active: %v\n", name, age, isActive)
}
2. 查询嵌套数据
// 继续上面的例子
// 访问嵌套对象
street := obj.Get("address").Get("street").String()
city := obj.Get("address").Get("city").String()
fmt.Printf("Address: %s, %s\n", street, city)
// 访问数组元素
firstHobby := obj.Get("hobbies").Index(0).String()
fmt.Printf("First hobby: %s\n", firstHobby)
3. 类型安全访问
jsonic提供了类型安全的方法来访问数据:
// 获取字符串(如果字段不存在或类型不匹配返回空字符串)
name := obj.Get("name").String()
// 获取整数(如果字段不存在或类型不匹配返回0)
age := obj.Get("age").Int()
// 获取布尔值(如果字段不存在或类型不匹配返回false)
isActive := obj.Get("isActive").Bool()
// 获取浮点数
price := obj.Get("price").Float()
// 检查字段是否存在
if obj.Has("email") {
email := obj.Get("email").String()
fmt.Println("Email:", email)
}
4. 遍历数组和对象
// 遍历数组
hobbies := obj.Get("hobbies")
for i := 0; i < hobbies.Len(); i++ {
fmt.Printf("Hobby %d: %s\n", i, hobbies.Index(i).String())
}
// 遍历对象(如果值是对象)
address := obj.Get("address")
for _, key := range address.Keys() {
fmt.Printf("%s: %s\n", key, address.Get(key).String())
}
5. 修改JSON数据
// 修改现有字段
obj.Get("name").Set("Alice")
// 添加新字段
obj.Set("email", "alice@example.com")
// 删除字段
obj.Del("isActive")
// 转换为JSON字符串
newJson, err := obj.Marshal()
if err != nil {
panic(err)
}
fmt.Println(string(newJson))
高级特性
1. 路径查询
// 使用路径查询嵌套值
city := obj.Path("address.city").String()
fmt.Println("City:", city)
// 查询数组元素
secondHobby := obj.Path("hobbies.1").String()
fmt.Println("Second hobby:", secondHobby)
2. 默认值
// 如果字段不存在或类型不匹配,使用默认值
phone := obj.Get("phone").StringOr("N/A")
fmt.Println("Phone:", phone)
age := obj.Get("age").IntOr(18) // 如果age不存在或不是数字,返回18
3. 类型判断
if obj.Get("name").IsString() {
fmt.Println("name is a string")
}
if obj.Get("age").IsNumber() {
fmt.Println("age is a number")
}
if obj.Get("address").IsObject() {
fmt.Println("address is an object")
}
if obj.Get("hobbies").IsArray() {
fmt.Println("hobbies is an array")
}
性能考虑
jsonic在易用性和性能之间取得了平衡。对于高性能场景,预先定义结构体并使用标准库的encoding/json
仍然是更好的选择。但对于快速开发和处理动态JSON数据,jsonic提供了很好的便利性。
总结
jsonic为Go开发者提供了一种无需预定义结构体就能类型安全地处理JSON数据的方式,特别适合:
- 处理动态或未知结构的JSON数据
- 快速原型开发
- 编写JSON处理工具
- 需要灵活查询JSON数据的场景
它的API设计简洁直观,减少了处理JSON数据时的样板代码,同时保持了类型安全性。