go语言中json操作总结(下)

1. make
  • slice : make([]T, length, [capacity])

  • map : make(map[K]V, [initial_capacity])(容量只是提示,可省略)

  • chan : make(chan T, [buffer_size])

    package main

    import "fmt"

    func main() {
    // slice
    list := make([]string, 2)
    list[0] = "Go"
    fmt.Println(list) // [Go ]

    复制代码
      // map
      counts := make(map[string]int)
      counts["apple"] = 5
      fmt.Println(counts) // map[apple:5]
    
      // chan
      ch := make(chan bool, 1)
      ch <- true
      fmt.Println(<-ch) // true

    }

2. gjson & sjson 实现 dict-CRUD
复制代码
package main

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

	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
)

// DynamicDict 是任意嵌套字典的类型别名
type DynamicDict = map[string]any

// ProfileManager 封装对 profile 的操作
type ProfileManager struct {
	data DynamicDict
}

// NewProfileManager 从 map 创建管理器
func NewProfileManager(initial DynamicDict) *ProfileManager {
	return &ProfileManager{data: initial}
}

// Get 查询任意路径的值,返回 gjson.Result(支持 .String(), .Int() 等)
func (pm *ProfileManager) Get(path string) gjson.Result {
	jsonBytes, err := json.Marshal(pm.data)
	if err != nil {
		log.Printf("Marshal error: %v", err)
		return gjson.Result{}
	}
	return gjson.GetBytes(jsonBytes, path)
}

// Set 修改或新增任意嵌套路径的值
func (pm *ProfileManager) Set(path string, value any) error {
	jsonBytes, err := json.Marshal(pm.data)
	if err != nil {
		return fmt.Errorf("marshal failed: %w", err)
	}

	newJSON, err := sjson.SetBytes(jsonBytes, path, value)
	if err != nil {
		return fmt.Errorf("sjson set failed: %w", err)
	}

	var newData DynamicDict
	if err := json.Unmarshal(newJSON, &newData); err != nil {
		return fmt.Errorf("unmarshal failed: %w", err)
	}

	pm.data = newData
	return nil
}

// Delete 删除指定路径的字段
func (pm *ProfileManager) Delete(path string) error {
	jsonBytes, err := json.Marshal(pm.data)
	if err != nil {
		return fmt.Errorf("marshal failed: %w", err)
	}

	newJSON, err := sjson.DeleteBytes(jsonBytes, path)
	if err != nil {
		return fmt.Errorf("sjson delete failed: %w", err)
	}

	var newData DynamicDict
	if err := json.Unmarshal(newJSON, &newData); err != nil {
		return fmt.Errorf("unmarshal failed: %w", err)
	}

	pm.data = newData
	return nil
}

// Dump 打印当前完整结构(格式化 JSON)
func (pm *ProfileManager) Dump() {
	output, _ := json.MarshalIndent(pm.data, "", "  ")
	fmt.Println(string(output))
}

// GetData 返回内部数据(可用于后续处理)
func (pm *ProfileManager) GetData() DynamicDict {
	return pm.data
}

// ====== 主程序演示 ======
func main() {
	// 初始动态嵌套字典(模拟从数据库/API 获取的用户 profile)
	initialProfile := DynamicDict{
		"id":   1001,
		"name": "Alice",
		"settings": map[string]any{
			"theme": "light",
			"lang":  "en",
			"privacy": map[string]any{
				"show_email": true,
			},
		},
		"tags": []any{"user", "beta"},
		"metadata": map[string]any{
			"created_at": "2023-01-01",
		},
	}

	// 创建管理器
	pm := NewProfileManager(initialProfile)

	fmt.Println("🟢 初始 profile:")
	pm.Dump()

	// 🔍 查询
	fmt.Println("\n🔍 查询 settings.theme:", pm.Get("settings.theme").String())
	fmt.Println("🔍 查询 privacy.show_email:", pm.Get("settings.privacy.show_email").Bool())

	// ✏️ 修改已有字段
	fmt.Println("\n✏️ 修改 settings.theme -> dark")
	_ = pm.Set("settings.theme", "dark")

	// ➕ 新增深层字段(自动创建中间层)
	fmt.Println("➕ 新增 settings.privacy.show_phone = false")
	_ = pm.Set("settings.privacy.show_phone", false)

	// ➕ 添加全新分支
	fmt.Println("➕ 新增 notifications.email.enabled = true")
	_ = pm.Set("notifications.email.enabled", true)

	// 🧪 修改数组(先设置整个数组)
	fmt.Println("🧪 设置 friends 数组")
	_ = pm.Set("friends", []any{
		map[string]any{"name": "Bob", "online": true},
		map[string]any{"name": "Carol", "online": false},
	})

	// ✏️ 修改数组中某个元素
	fmt.Println("✏️ 修改 friends.0.online -> false")
	_ = pm.Set("friends.0.online", false)

	// 🗑️ 删除字段
	fmt.Println("🗑️ 删除 tags 字段")
	_ = pm.Delete("tags")

	// 🗑️ 删除整个子对象
	fmt.Println("🗑️ 删除 metadata")
	_ = pm.Delete("metadata")

	// ✅ 最终结果
	fmt.Println("\n✅ 最终 profile:")
	pm.Dump()

	// 🔁 验证:从 manager 获取数据并访问
	final := pm.GetData()
	if settings, ok := final["settings"].(map[string]any); ok {
		if privacy, ok := settings["privacy"].(map[string]any); ok {
			fmt.Printf("\n验证: show_phone = %v\n", privacy["show_phone"])
		}
	}
}
3. gjson & sjson 实现JSON 结构(对象、数组、混合)的 CRUD
复制代码
package main

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

	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
)

// GenericJSON 表示任意 JSON 值(对象、数组、字符串等)
type GenericJSON = any

// JSONManager 管理任意 JSON 数据
type JSONManager struct {
	data GenericJSON
}

// NewJSONManager 创建管理器
func NewJSONManager(initial GenericJSON) *JSONManager {
	return &JSONManager{data: initial}
}

// Get 查询路径(支持数组索引、嵌套等)
func (jm *JSONManager) Get(path string) gjson.Result {
	jsonBytes, err := json.Marshal(jm.data)
	if err != nil {
		log.Printf("Marshal error: %v", err)
		return gjson.Result{}
	}
	return gjson.GetBytes(jsonBytes, path)
}

// Set 修改或新增路径(自动处理对象/数组)
func (jm *JSONManager) Set(path string, value any) error {
	jsonBytes, err := json.Marshal(jm.data)
	if err != nil {
		return fmt.Errorf("marshal failed: %w", err)
	}

	newJSON, err := sjson.SetBytes(jsonBytes, path, value)
	if err != nil {
		return fmt.Errorf("sjson set failed: %w", err)
	}

	var newData GenericJSON
	if err := json.Unmarshal(newJSON, &newData); err != nil {
		return fmt.Errorf("unmarshal failed: %w", err)
	}

	jm.data = newData
	return nil
}

// Delete 删除路径
func (jm *JSONManager) Delete(path string) error {
	jsonBytes, err := json.Marshal(jm.data)
	if err != nil {
		return fmt.Errorf("marshal failed: %w", err)
	}

	newJSON, err := sjson.DeleteBytes(jsonBytes, path)
	if err != nil {
		return fmt.Errorf("sjson delete failed: %w", err)
	}

	var newData GenericJSON
	if err := json.Unmarshal(newJSON, &newData); err != nil {
		return fmt.Errorf("unmarshal failed: %w", err)
	}

	jm.data = newData
	return nil
}

// Dump 打印格式化 JSON
func (jm *JSONManager) Dump() {
	output, _ := json.MarshalIndent(jm.data, "", "  ")
	fmt.Println(string(output))
}

// GetData 返回原始数据
func (jm *JSONManager) GetData() GenericJSON {
	return jm.data
}

// ====== 演示各种场景 ======
func main() {
	fmt.Println("=== 场景 1: 顶层是字典(对象) ===")
	objData := map[string]any{
		"name": "Alice",
		"friends": []any{
			map[string]any{"name": "Bob", "age": 30},
			map[string]any{"name": "Carol"},
		},
	}
	mgr1 := NewJSONManager(objData)
	_ = mgr1.Set("friends.0.age", 31)
	_ = mgr1.Set("friends.1.tags", []string{"admin"})
	mgr1.Dump()

	fmt.Println("\n=== 场景 2: 顶层是列表(数组) ===")
	arrData := []any{
		map[string]any{"id": 1, "active": true},
		map[string]any{"id": 2, "active": false},
	}
	mgr2 := NewJSONManager(arrData)
	_ = mgr2.Set("0.active", false)           // 修改第一个元素的 active
	_ = mgr2.Set("1.name", "NewItem")         // 给第二个元素加字段
	_ = mgr2.Set("-1.status", "archived")     // -1 表示最后一个
	mgr2.Dump()

	fmt.Println("\n=== 场景 3: 深度混合嵌套 ===")
	complexData := map[string]any{
		"results": []any{
			map[string]any{
				"metadata": map[string]any{
					"tags": []any{"a", "b"},
				},
				"items": []any{
					map[string]any{"value": 100},
					map[string]any{"value": 200},
				},
			},
		},
	}
	mgr3 := NewJSONManager(complexData)
	_ = mgr3.Set("results.0.metadata.tags.2", "c")      // 追加到 tags
	_ = mgr3.Set("results.0.items.1.value", 250)        // 修改 items[1].value
	_ = mgr3.Set("results.0.new_flag", true)            // 新增字段
	mgr3.Dump()

	fmt.Println("\n=== 查询验证 ===")
	fmt.Println("场景1 friends.0.age =", mgr1.Get("friends.0.age").Int())
	fmt.Println("场景2 第二个元素 name =", mgr2.Get("1.name").String())
	fmt.Println("场景3 tags =", mgr3.Get("results.0.metadata.tags").String())
}
相关推荐
benchmark_cc4 小时前
A 股、港股、美股如何建立统一的标的主数据格式?
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
翊众建站5 小时前
用 JSON-LD 给企业官网做结构化数据:LocalBusiness 与 FAQPage 实践笔记
人工智能·搜索引擎·json
sibylyue6 小时前
BI(商业智能)
数据分析
Patrick_Wilson6 小时前
Go 为什么需要 defer?从函数怎么收尾说起
后端·go·编程语言
Patrick_Wilson7 小时前
从文本输出理解 Go 方法与接口
后端·go·编程语言
benchmark_cc8 小时前
用 00700.HK 做港股行情清洗:字段核对、校验与个人量化开发实践
python·数据分析·pandas·量化交易·股票数据·quantdash
Zhao-Jichao10 小时前
AI Prompting for Everyone 课程笔记 - P19 数据分析 Data Analysis
人工智能·笔记·数据分析
第九序言T10 小时前
数据分析岗 Pandas 面试题 20 道(上):概念与读代码
python·数据分析·pandas·数据处理
奥惟斯11 小时前
GEO 上线前,先把这 3 类实体信号地基补上
人工智能·深度学习·机器学习·自然语言处理·数据挖掘·数据分析·知识图谱
2601_9669496511 小时前
如何封装 qd.klines.batch(),让批量 K 线查询函数在多个策略中复用?
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash