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

1 回复

更多关于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数据的方式,特别适合:

  1. 处理动态或未知结构的JSON数据
  2. 快速原型开发
  3. 编写JSON处理工具
  4. 需要灵活查询JSON数据的场景

它的API设计简洁直观,减少了处理JSON数据时的样板代码,同时保持了类型安全性。

回到顶部