golang高效JSON查询与处理插件库gojq的使用

golang高效JSON查询与处理插件库gojq的使用

简介

gojq 是一个用于在 Golang 中进行 JSON 查询的库。它主要提供以下功能:

  • 使解析 JSON 配置文件更加容易
  • 支持 JSON 表达式求值
  • 减少类型断言解析 JSON 的痛苦

安装

go get -u github.com/elgs/gojq

从 JSON 对象查询

package main

import (
	"fmt"
	"github.com/elgs/gojq"
)

var jsonObj = `
{
  "name": "sam",
  "gender": "m",
  "pet": null,
  "skills": [
    "Eating",
    "Sleeping",
    "Crawling"
  ],
  "hello.world":true
}
`

func main() {
	parser, err := gojq.NewStringQuery(jsonObj)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(parser.Query("name"))          // sam <nil>
	fmt.Println(parser.Query("gender"))        // m <nil>
	fmt.Println(parser.Query("skills.[1]"))    // Sleeping <nil>
	fmt.Println(parser.Query("hello"))         // <nil> hello does not exist.
	fmt.Println(parser.Query("pet"))           // <nil> <nil>
	fmt.Println(parser.Query("."))             // map[name:sam gender:m pet:<nil> skills:[Eating Sleeping Crawling] hello.world:true] <nil>
	fmt.Println(parser.Query("'hello.world'")) // true <nil>
}

从 JSON 数组查询

package main

import (
	"fmt"
	"github.com/elgs/gojq"
)

var jsonArray = `
[
  {
    "name": "elgs",
    "gender": "m",
    "skills": [
      "Golang",
      "Java",
      "C"
    ]
  },
  {
    "name": "enny",
    "gender": "f",
    "skills": [
      "IC",
      "Electric design",
      "Verification"
    ]
  },
  {
    "name": "sam",
    "gender": "m",
	"pet": null,
    "skills": [
      "Eating",
      "Sleeping",
      "Crawling"
    ]
  }
]
`

func main() {
	parser, err := gojq.NewStringQuery(jsonArray)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(parser.Query("[0].name"))       // elgs <nil>
	fmt.Println(parser.Query("[1].gender"))     // f <nil>
	fmt.Println(parser.Query("[2].skills.[1]")) // Sleeping <nil>
	fmt.Println(parser.Query("[2].hello"))      // <nil> hello does not exist.
	fmt.Println(parser.Query("[2].pet"))        // <nil> <nil>
}

嵌套查询

package main

import (
	"fmt"
	"github.com/elgs/gojq"
)

var jsonArray = `
[
  {
    "name": "elgs",
    "gender": "m",
    "skills": [
      "Golang",
      "Java",
      "C"
    ]
  },
  {
    "name": "enny",
    "gender": "f",
    "skills": [
      "IC",
      "Electric design",
      "Verification"
    ]
  },
  {
    "name": "sam",
    "gender": "m",
	"pet": null,
    "skills": [
      "Eating",
      "Sleeping",
      "Crawling"
    ]
  }
]
`

func main() {
	parser, err := gojq.NewStringQuery(jsonArray)
	if err != nil {
		fmt.Println(err)
		return
	}
	samSkills, err := parser.Query("[2].skills")
	fmt.Println(samSkills, err) //[Eating Sleeping Crawling] <nil>
	samSkillParser := gojq.NewQuery(samSkills)
	fmt.Println(samSkillParser.Query("[1]")) //Sleeping <nil>
}

通过以上示例可以看到,gojq 提供了简单直观的方式来查询和操作 JSON 数据,无论是对象还是数组,甚至是嵌套结构,都能轻松处理。


更多关于golang高效JSON查询与处理插件库gojq的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高效JSON查询与处理插件库gojq的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Gojq: 高效的Golang JSON查询与处理库

gojq是一个纯Go实现的jq兼容JSON查询和处理库,它提供了强大的JSON数据查询和转换能力,同时保持了高性能和低内存消耗。

安装

go get github.com/itchyny/gojq

基本使用

1. 简单查询

package main

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/itchyny/gojq"
)

func main() {
	query, err := gojq.Parse(".name")
	if err != nil {
		log.Fatalln(err)
	}

	input := map[string]interface{}{"name": "Alice", "age": 30}
	iter := query.Run(input)

	for {
		v, ok := iter.Next()
		if !ok {
			break
		}
		if err, ok := v.(error); ok {
			log.Fatalln(err)
		}
		fmt.Printf("%#v\n", v) // 输出: "Alice"
	}
}

2. 复杂查询

func complexQuery() {
	jsonStr := `{
		"users": [
			{"id": 1, "name": "Alice", "roles": ["admin", "user"]},
			{"id": 2, "name": "Bob", "roles": ["user"]},
			{"id": 3, "name": "Charlie", "roles": ["user", "editor"]}
		]
	}`

	var input interface{}
	if err := json.Unmarshal([]byte(jsonStr), &input); err != nil {
		log.Fatal(err)
	}

	query, err := gojq.Parse(".users[] | select(.roles[] | contains(\"admin\")) | .name")
	if err != nil {
		log.Fatal(err)
	}

	iter := query.Run(input)
	for {
		v, ok := iter.Next()
		if !ok {
			break
		}
		if err, ok := v.(error); ok {
			log.Fatal(err)
		}
		fmt.Println(v) // 输出: "Alice"
	}
}

高级特性

1. 自定义函数

func customFunction() {
	query, err := gojq.Parse(`
		def to_upper: ascii_upcase;
		.users[].name | to_upper
	`)
	if err != nil {
		log.Fatal(err)
	}

	input := map[string]interface{}{
		"users": []interface{}{
			map[string]interface{}{"name": "Alice"},
			map[string]interface{}{"name": "Bob"},
		},
	}

	iter := query.Run(input)
	for {
		v, ok := iter.Next()
		if !ok {
			break
		}
		if err, ok := v.(error); ok {
			log.Fatal(err)
		}
		fmt.Println(v) // 输出: "ALICE" 然后 "BOB"
	}
}

2. 多步骤数据处理

func multiStageProcessing() {
	jsonStr := `{
		"products": [
			{"id": 1, "name": "Laptop", "price": 999.99, "stock": 5},
			{"id": 2, "name": "Mouse", "price": 19.99, "stock": 42},
			{"id": 3, "name": "Keyboard", "price": 49.99, "stock": 12}
		]
	}`

	var input interface{}
	if err := json.Unmarshal([]byte(jsonStr), &input); err != nil {
		log.Fatal(err)
	}

	query, err := gojq.Parse(`
		.products[]
		| select(.price < 50)
		| {name, total_value: (.price * .stock)}
		| select(.total_value > 200)
	`)
	if err != nil {
		log.Fatal(err)
	}

	iter := query.Run(input)
	for {
		v, ok := iter.Next()
		if !ok {
			break
		}
		if err, ok := v.(error); ok {
			log.Fatal(err)
		}
		fmt.Printf("%+v\n", v)
		// 输出: map[name:Mouse total_value:839.58]
		//        map[name:Keyboard total_value:599.88]
	}
}

性能优化技巧

  1. 预编译查询:对于重复使用的查询,先Parse然后复用Query对象
  2. 使用迭代器:直接处理迭代器结果而不是收集到数组中
  3. 合理使用流式处理:对于大JSON文件,考虑结合json.Decoder使用
func performanceOptimization() {
	// 预编译查询
	query, err := gojq.Parse(".items[].id")
	if err != nil {
		log.Fatal(err)
	}

	// 大文件流式处理
	file, err := os.Open("large.json")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	dec := json.NewDecoder(file)
	for {
		var data interface{}
		if err := dec.Decode(&data); err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		iter := query.Run(data)
		for {
			v, ok := iter.Next()
			if !ok {
				break
			}
			if err, ok := v.(error); ok {
				log.Fatal(err)
			}
			// 处理结果
			fmt.Println(v)
		}
	}
}

与标准库对比

gojq相比标准库的json包提供了更强大的查询能力:

  1. 复杂查询:可以轻松实现嵌套查询、过滤、映射等
  2. 数据转换:支持复杂的数据格式转换
  3. 更简洁:使用类似jq的DSL语法,代码更简洁

总结

gojq是Golang中处理JSON数据的强大工具,特别适合需要复杂查询和转换的场景。它兼容jq语法,学习曲线平缓,性能优异,是标准库json包的有力补充。

回到顶部