GoJsonQ 学习与使用指南

GoJsonQ 是一个用于在 Go 语言中查询和处理 JSON 数据的轻量级库。它提供了类似于 SQL 的查询功能,使得对复杂的 JSON 数据进行过滤、排序、分组等操作变得更加简便。

目录

  1. 安装 GoJsonQ
  2. 基本用法
  3. 高级功能
  4. 示例代码
  5. 常见问题
  6. 资源与参考资料

安装 GoJsonQ

在开始使用 GoJsonQ 之前,需要先安装该库。确保你已经安装了 Go 语言环境。

使用 go get 命令安装 GoJsonQ:

go get -u github.com/thedevsaddam/gojsonq/v2

或在 go.mod 文件中添加:

require github.com/thedevsaddam/gojsonq/v2 v2.x.x

然后运行 go mod tidy 以下载依赖。


基本用法

1. 导入包

import (
    "fmt"
    "github.com/thedevsaddam/gojsonq/v2"
)

2. 加载 JSON 数据

可以从多种数据源加载 JSON,例如字符串、文件或字节切片。

从字符串加载
jsonString := `{
    "users": [
        {"id": 1, "name": "Alice", "age": 30},
        {"id": 2, "name": "Bob", "age": 25},
        {"id": 3, "name": "Charlie", "age": 35}
    ]
}`

jq := gojsonq.New().FromString(jsonString)
从文件加载
jq := gojsonq.New().FromFile("data.json")

3. 查询数据

获取所有数据
data := jq.Get()
fmt.Println(data)
使用 Find 查找单个对象
user := jq.Find("users.id", 2)
fmt.Println(user)
使用 Where 过滤数据
result := jq.Where("age", ">", 28).Get()
fmt.Println(result)
选择特定字段
names := jq.Pluck("users.name").Get()
fmt.Println(names)
排序
sorted := jq.SortBy("age").Get()
fmt.Println(sorted)

高级功能

1. 链式调用

GoJsonQ 支持链式调用,使查询更加简洁。

usersOver30 := gojsonq.New().
    FromString(jsonString).
    Find("users.age", func(age int) bool { return age > 30 }).
    Get()

fmt.Println(usersOver30)

2. 聚合函数

支持多种聚合操作,如 Count, Max, Min, Avg, Sum 等。

count := jq.Count("users")
maxAge := jq.Max("users.age")
avgAge := jq.Avg("users.age")

fmt.Println("Count:", count)
fmt.Println("Max Age:", maxAge)
fmt.Println("Average Age:", avgAge)

3. 分组

可以根据特定字段进行分组。

grouped := jq.GroupBy("users.age").Get()
fmt.Println(grouped)

4. 多条件查询

支持多个条件的组合查询。

filtered := jq.
    Where("age", ">", 25).
    Where("name", "Alice").
    Get()
    
fmt.Println(filtered)

5. 嵌套查询

处理嵌套的 JSON 结构。

address := `{
    "users": [
        {
            "id": 1,
            "name": "Alice",
            "address": {
                "city": "New York",
                "zip": "10001"
            }
        },
        {
            "id": 2,
            "name": "Bob",
            "address": {
                "city": "Los Angeles",
                "zip": "90001"
            }
        }
    ]
}`

jq := gojsonq.New().FromString(address)
cities := jq.Pluck("users.address.city").Get()
fmt.Println(cities)

示例代码

以下是一个完整的示例,展示如何使用 GoJsonQ 进行各种操作。

package main

import (
    "fmt"
    "github.com/thedevsaddam/gojsonq/v2"
)

func main() {
    jsonData := `{
        "users": [
            {"id": 1, "name": "Alice", "age": 30, "city": "New York"},
            {"id": 2, "name": "Bob", "age": 25, "city": "Los Angeles"},
            {"id": 3, "name": "Charlie", "age": 35, "city": "Chicago"},
            {"id": 4, "name": "David", "age": 28, "city": "New York"},
            {"id": 5, "name": "Eve", "age": 22, "city": "Los Angeles"}
        ]
    }`

    jq := gojsonq.New().FromString(jsonData)

    // 获取所有用户
    allUsers := jq.Find("users")
    fmt.Println("All Users:", allUsers)

    // 过滤年龄大于25的用户
    usersOver25 := jq.Where("age", ">", 25).Get()
    fmt.Println("Users over 25:", usersOver25)

    // 获取特定字段
    names := jq.Pluck("users.name").Get()
    fmt.Println("Names:", names)

    // 排序
    sortedByAge := jq.SortBy("age").Get()
    fmt.Println("Sorted by Age:", sortedByAge)

    // 聚合函数
    count := jq.Count("users")
    maxAge := jq.Max("users.age")
    avgAge := jq.Avg("users.age")
    fmt.Println("Count:", count)
    fmt.Println("Max Age:", maxAge)
    fmt.Println("Average Age:", avgAge)
}

输出:

All Users: [map[id:1 name:Alice age:30 city:New York] map[id:2 name:Bob age:25 city:Los Angeles] map[id:3 name:Charlie age:35 city:Chicago] map[id:4 name:David age:28 city:New York] map[id:5 name:Eve age:22 city:Los Angeles]]
Users over 25: [map[id:1 name:Alice age:30 city:New York] map[id:3 name:Charlie age:35 city:Chicago] map[id:4 name:David age:28 city:New York]]
Names: [Alice Bob Charlie David Eve]
Sorted by Age: [map[id:5 name:Eve age:22 city:Los Angeles] map[id:2 name:Bob age:25 city:Los Angeles] map[id:4 name:David age:28 city:New York] map[id:1 name:Alice age:30 city:New York] map[id:3 name:Charlie age:35 city:Chicago]]
Count: 5
Max Age: 35
Average Age: 28

YAML 文件处理与 GoJsonQ 的 JSON 查询功能

为了结合 YAML 文件处理与 GoJsonQ 的 JSON 查询功能,你可以将 YAML 文件解析为 JSON 或等效的 Go 数据结构,然后使用 GoJsonQ 进行查询处理。

在 Go 中,可以使用官方的 gopkg.in/yaml.v2 包来解析 YAML 数据,将其转换为结构化的 Go 数据类型。接着,你可以使用 GoJsonQ 对转换后的数据进行查询。

首先,你需要安装 YAML 解析库 gopkg.in/yaml.v2。通过 Go 的 go get 命令来安装:

go get gopkg.in/yaml.v2

使用 yaml.Unmarshal() 函数将 YAML 数据解析为 Go 的 map[string]interface{} 或结构体。然后,使用 GoJsonQ 查询该数据。

为了让 GoJsonQ 处理 YAML 文件,首先需要解析 YAML 文件并将其转换为等效的 JSON 格式(即 map[string]interface{}),然后传递给 GoJsonQ。

步骤如下:

  1. 使用 yaml.Unmarshal() 解析 YAML 数据。
  2. 将解析后的数据作为 GoJsonQ 的数据源。
  3. 对数据进行查询和处理。

假设有一个 YAML 文件 data.yaml,内容如下:

users:
  - id: 1
    name: Alice
    age: 30
  - id: 2
    name: Bob
    age: 25
  - id: 3
    name: Charlie
    age: 35

你可以使用以下步骤解析 YAML 并使用 GoJsonQ 进行查询。

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "github.com/thedevsaddam/gojsonq/v2"
    "gopkg.in/yaml.v2"
)

func main() {
    // 读取 YAML 文件
    yamlFile, err := ioutil.ReadFile("data.yaml")
    if err != nil {
        log.Fatalf("Error reading YAML file: %v", err)
    }

    // 定义一个 map 来存储解析后的数据
    var data map[string]interface{}

    // 解析 YAML 数据
    err = yaml.Unmarshal(yamlFile, &data)
    if err != nil {
        log.Fatalf("Error unmarshaling YAML: %v", err)
    }

    // 打印解析后的数据 (用于调试)
    fmt.Printf("Parsed YAML data: %#v\n", data)

    // 使用 GoJsonQ 查询解析后的数据
    jq := gojsonq.New().FromInterface(data)

    // 查询所有用户数据
    allUsers := jq.Find("users")
    fmt.Println("All Users:", allUsers)

    // 过滤年龄大于 25 的用户
    usersOver25 := jq.Where("age", ">", 25).Get()
    fmt.Println("Users over 25:", usersOver25)

    // 获取所有用户的姓名
    names := jq.Pluck("users.name").Get()
    fmt.Println("Names:", names)
}
Parsed YAML data: map[string]interface {}{"users":[]interface {}{map[interface {}]interface {}{"id":1, "name":"Alice", "age":30}, map[interface {}]interface {}{"id":2, "name":"Bob", "age":25}, map[interface {}]interface {}{"id":3, "name":"Charlie", "age":35}}}
All Users: [map[id:1 name:Alice age:30] map[id:2 name:Bob age:25] map[id:3 name:Charlie age:35]]
Users over 25: [map[id:1 name:Alice age:30] map[id:3 name:Charlie age:35]]
Names: [Alice Bob Charlie]

在解析时,你可能注意到输出中的数据结构是 map[interface{}]interface{},为了兼容性并便于查询,你可以将其转换为 map[string]interface{}。这是因为 YAML 文件中的键和值可以是任意类型,而 JSON 键通常是字符串。

可以使用递归函数将 map[interface{}]interface{} 转换为 map[string]interface{}

递归转换函数
func convertMapInterface(m interface{}) interface{} {
    switch m := m.(type) {
    case map[interface{}]interface{}:
        converted := make(map[string]interface{})
        for k, v := range m {
            converted[k.(string)] = convertMapInterface(v)
        }
        return converted
    case []interface{}:
        for i, v := range m {
            m[i] = convertMapInterface(v)
        }
    }
    return m
}

使用该函数来处理解析后的 YAML 数据:

data = convertMapInterface(data).(map[string]interface{})

这样可以确保数据结构可以更好地适应 JSON 风格的查询。


示例代码(修正版本)

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "github.com/thedevsaddam/gojsonq/v2"
    "gopkg.in/yaml.v2"
)

// 递归转换 map[interface{}]interface{} 为 map[string]interface{}
func convertMapInterface(m interface{}) interface{} {
    switch m := m.(type) {
    case map[interface{}]interface{}:
        converted := make(map[string]interface{})
        for k, v := range m {
            converted[k.(string)] = convertMapInterface(v)
        }
        return converted
    case []interface{}:
        for i, v := range m {
            m[i] = convertMapInterface(v)
        }
    }
    return m
}

func main() {
    // 读取 YAML 文件
    yamlFile, err := ioutil.ReadFile("data.yaml")
    if err != nil {
        log.Fatalf("Error reading YAML file: %v", err)
    }

    // 定义一个 map 来存储解析后的数据
    var data map[string]interface{}

    // 解析 YAML 数据
    err = yaml.Unmarshal(yamlFile, &data)
    if err != nil {
        log.Fatalf("Error unmarshaling YAML: %v", err)
    }

    // 转换为 JSON 友好的格式
    data = convertMapInterface(data).(map[string]interface{})

    // 使用 GoJsonQ 查询解析后的数据
    jq := gojsonq.New().FromInterface(data)

    // 查询所有用户数据
    allUsers := jq.Find("users")
    fmt.Println("All Users:", allUsers)

    // 过滤年龄大于 25 的用户
    usersOver25 := jq.Where("age", ">", 25).Get()
    fmt.Println("Users over 25:", usersOver25)

    // 获取所有用户的姓名
    names := jq.Pluck("users.name").Get()
    fmt.Println("Names:", names)
}

常见问题

1. 如何处理深度嵌套的 YAML 文件?

对于嵌套较深的 YAML 文件,确保递归函数能够处理所有嵌套层级的数据,并且 GoJsonQ 的 dot notation 可以方便地访问嵌套的字段。

2. YAML 中的数据类型如何映射到 Go?

YAML 的数据类型(例如布尔值、整数、字符串等)自动映射到 Go 的相应数据类型,例如 bool, int, string 等。对于复杂对象或数组,映射为 map[interface{}]interface{}[]interface{},这需要手动转换为 map[string]interface{} 格式。


通过这份集成指南,你可以轻松将 YAML 文件与 GoJsonQ 结合,进行灵活的查询和处理。如果你有更复杂的需求或遇到其他问题,欢迎继续提问!

3. 如何处理大型 JSON 文件?

对于非常大的 JSON 文件,建议分块读取或使用流式解析,以避免内存占用过高。GoJsonQ 目前不支持流式解析,但可以结合 encoding/json 包进行预处理。

4. 支持哪些查询操作符?

GoJsonQ 支持常见的操作符,如 =, !=, <, >, <=, >=, in, not in, like 等。

5. 如何处理嵌套数组或对象?

可以使用点(.)语法访问嵌套的字段。例如,users.address.city


资源与参考资料

  • 官方文档: GoJsonQ GitHub
  • 示例项目: 可以在 GitHub 上搜索相关示例项目,学习实际应用案例。
  • 社区支持: 在 GitHub Issues 区域提问或查看已有的问题,以获取帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/888930.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot智能垃圾分类系统【附源码】

基于SpringBoot智能垃圾分类系统 效果如下&#xff1a; 系统首页界面 用户注册界面 垃圾站点页面 商品兑换页面 管理员登录界面 垃圾投放界面 物业登录界面 物业功能界图 研究背景 随着城市化进程的加速&#xff0c;生活垃圾的产量急剧增加&#xff0c;传统的垃圾分类方式已…

【C++】二叉搜索树+变身 = AVL树

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言一、AVL树二、AVL树的实现2.1 平衡因子2.2 旋转处理2.2.1 左单旋&#xff1a;插入新节点后单纯的右边高2.2.2 …

光路科技TSN交换机:驱动自动驾驶技术革新,保障高精度实时数据传输

自动驾驶技术正快速演进&#xff0c;对实时数据处理能力的需求激增。光路科技推出的TSN&#xff08;时间敏感网络&#xff09;交换机&#xff0c;在比亚迪最新车型中的成功应用&#xff0c;显著推动了这一领域的技术进步。 自动驾驶技术面临的挑战 自动驾驶系统需整合来自雷达…

大模型基础:基本概念、Prompt、RAG、Agent及多模态

随着大模型的迅猛发展&#xff0c;LLM 作为人工智能的核心力量&#xff0c;正以前所未有的方式重塑着我们的生活、学习和工作。无论是智能语音助手、自动驾驶汽车&#xff0c;还是智能决策系统&#xff0c;大模型都是幕后英雄&#xff0c;让这些看似不可思议的事情变为可能。本…

43 C 程序动态内存分配:内存区域划分、void 指针、内存分配相关函数(malloc、calloc、realloc、_msize、free)、内存泄漏

目录 1 C 程序内存区域划分 1.1 代码区 (Code Section) 1.2 全局/静态区 (Global/Static Section) 1.3 栈区 (Stack Section) 1.4 堆区 (Heap Section) 1.5 动态内存分配 2 void 指针&#xff08;无类型指针&#xff09; 2.1 void 指针介绍 2.2 void 指针的作用 2.3 …

Java基本数据类型和String类型的转换

1.基本介绍 在程序开发中&#xff0c;我们经常需要将基本数据类型转换成String类型。或者将String类型转为基本数据类型。 2.基本类型转String类型 语法&#xff1a;将 基本数据类型的值 “” 即可 3.String类型转基本数据类型 语法&#xff1a;通过基本类型的包装类调用…

【DataSophon】DataSophon1.2.1 整合Zeppelin并配置Hive|Trino|Spark解释器

目录 ​一、Zeppelin简介 二、实现步骤 2.1 Zeppelin包下载 2.2 work配置文件 三、配置常用解释器 3.1配置Hive解释器 3.2 配置trino解释器 3.3 配置Spark解释器 一、Zeppelin简介 Zeppelin是Apache基金会下的一个开源框架&#xff0c;它提供了一个数据可视化的框架&am…

浏览器动态移动的小球源码分享

浏览器动态移动的小球源码分享 <script>(function(a){var width100,height100,borderRadius100,circlefunction(){};circle.prototype{color:function(){let colour "#"Math.floor(Math.random()*255).toString(16)Math.floor(Math.random()*255).toString…

爬虫案例——爬取腾讯社招

案例需求&#xff1a; 1.爬取腾讯社招的数据&#xff08;搜索 | 腾讯招聘&#xff09;包括岗位名称链接时间公司名称 2.爬取所有页&#xff08;翻页&#xff09; 3.利用jsonpath进行数据解析 4.保存数据&#xff1a;txt文本形式和excel文件两种形式 解析&#xff1a; 1.分…

hdfs伪分布式集群搭建

1 准备 vmware 虚拟三台centos系统的节点三台机器安装好jdk环境关闭防火墙&#xff08;端口太多&#xff0c;需要的自行去开关端口&#xff09;hadoop压缩包解压至三台服务器 可在一台节点上配置完成后克隆为三台节点 2 host修改 vi /etc/hosts在每个节点上添加三台机器的i…

【Linux】Shell脚本基础+条件判断与循环控制

目录 一、介绍 1. Linux提供的Shell解析器 2. bash和sh关系 3. Centos默认的Shell解析器是bash 二、定义 1. 变量名的定义规则 2. 等号周围没有空格 3. 查看变量 4. 删除变量 5. 正确地定义数组 6. 将局部环境变量提升为全局 7. 正确选择引号 8. 特殊变量名 三…

QT实现QMessageBox中文按钮

这是我记录Qt学习过程心得文章的第二篇&#xff0c;主要是为了方便QMessageBox弹出框的使用&#xff0c;通过自定义的方式&#xff0c;将其常用的功能&#xff0c;统一封装成一个函数&#xff0c;还是写在了Skysonya类里面。 实现代码&#xff1a; //中文提示对话框 bool Sky…

Python爬虫使用示例-古诗词摘录

一、分析需求 目标地址&#xff1a; https://www.sou-yun.cn/Query.aspx?typepoem&id二、提取诗句 import os import re import requests import parsel#url https://www.sou-yun.cn/PoemIndex.aspx?dynastyTang&author14976&typeJie urlhttps://www.sou-yun.…

【PGCCC】在 Postgres 上构建图像搜索引擎

我最近看到的最有趣的电子商务功能之一是能够搜索与我手机上的图片相似的产品。例如&#xff0c;我可以拍一双鞋或其他产品的照片&#xff0c;然后搜索产品目录以查找类似商品。使用这样的功能可以是一个相当简单的项目&#xff0c;只要有合适的工具。如果我们可以将问题定义为…

apisix云原生网关

定义 企业级网关通过域名、路由将请求分发到对应的应用上&#xff0c;通常承载数千个服务的流量&#xff0c;对稳定性有较高要求。 CNCF全景图 选型 Kubernetes抽象出两个核心概念&#xff1a;Service&#xff0c;为多个Pod提供统一的访问入口&#xff1b;Ingress&#xff…

汽车车轮平衡块行业前景:预计2030年全球市场规模将达到10亿美元

汽车车轮平衡块&#xff0c;也称为轮胎平衡块&#xff0c;是一种安装在车轮上的配重部件。它的主要作用是帮助车轮在高速旋转状态下保持动平衡。当车轮高速旋转时&#xff0c;由于车轮的动态不平衡状态&#xff0c;会导致车辆在行驶中出现车轮抖动和方向盘震动的现象。汽车车轮…

VSOMEIP代码阅读整理(1) - 网卡状态监听

一. 概述 在routing进程所使用的配置文件中&#xff0c;存在如下配置项目&#xff1a;{"unicast" : "192.168.56.101",..."service-discovery" :{"enable" : "true","multicast" : "224.244.224.245",…

【数据结构】栈和队列 + 经典算法题

目录 前言 一、栈 二、栈的实现 三、栈的循环遍历演示 四、栈的算法题 // 一、队列 二、队列的实现 三、使用演示 四、队列的算法题 总结 前言 本文完整实现了栈和队列的数据结构&#xff0c;以及栈和队列的一些经典算法题&#xff0c;让我们更加清楚了解这两种数据…

昇思MindSpore进阶教程--数据处理性能优化(中)

大家好&#xff0c;我是刘明&#xff0c;明志科技创始人&#xff0c;华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享&#xff0c;如果你也喜欢我的文章&#xff0c;就点个关注吧 shuffle性能优化 shuffle操作主要是对有…

PCB缺陷检测数据集 xml 可转yolo格式 ,共10688张图片

PCB缺陷检测数据集&#xff08;yolov5,v7,v8&#xff09; 数据集总共有两个文件夹&#xff0c;一个是pcb整体标注&#xff0c;一个是pcb部分截图。 整体标注有6个分类&#xff0c;开路&#xff0c;短路等都已经标注&#xff0c;标注格式为xml&#xff0c;每个文件夹下有100多张…