Rust JSON路径处理库serde_json_path_macros的使用,高效解析与操作JSON数据路径

Rust JSON路径处理库serde_json_path_macros的使用,高效解析与操作JSON数据路径

serde_json_path_macros是为serde_json_path crate提供的宏支持。

安装

在项目目录中运行以下Cargo命令:

cargo add serde_json_path_macros

或者在Cargo.toml中添加以下行:

serde_json_path_macros = "0.1.6"

完整示例代码

以下是一个使用serde_json_path_macros处理JSON路径的完整示例:

use serde_json::{json, Value};
use serde_json_path::JsonPath;
use serde_json_path_macros::json_path;

fn main() {
    // 创建一个示例JSON数据
    let data: Value = json!({
        "store": {
            "book": [
                {
                    "category": "reference",
                    "author": "Nigel Rees",
                    "title": "Sayings of the Century",
                    "price": 8.95
                },
                {
                    "category": "fiction",
                    "author": "Evelyn Waugh",
                    "title": "Sword of Honour",
                    "price": 12.99
                }
            ],
            "bicycle": {
                "color": "red",
                "price": 19.95
            }
        }
    });

    // 使用宏创建JSON路径
    let path = json_path!("$.store.book[*].author");
    
    // 执行查询
    let authors = path.query(&data).all();
    
    // 输出结果
    println!("Authors: {:?}", authors);
    // 输出: Authors: ["Nigel Rees", "Evelyn Waugh"]

    // 另一个示例 - 获取所有价格
    let prices_path = json_path!("$..price");
    let prices = prices_path.query(&data).all();
    println!("Prices: {:?}", prices);
    // 输出: Prices: [8.95, 12.99, 19.95]

    // 使用条件过滤
    let expensive_books = json_path!("$.store.book[?(@.price > 10)]")
        .query(&data)
        .all();
    println!("Expensive books: {:?}", expensive_books);
    // 输出: Expensive books: [{"category": "fiction", "author": "Evelyn Waugh", ...}]
}

主要功能

  1. 使用json_path!宏创建JSON路径表达式
  2. 支持标准JSONPath语法:
    • $ 表示根对象
    • .[] 用于子节点访问
    • * 通配符匹配所有元素
    • .. 递归下降
    • ?(<expression>) 过滤表达式

完整示例demo

基于上述内容,这里提供一个更完整的示例代码,展示更多JSON路径操作:

use serde_json::{json, Value};
use serde_json_path::JsonPath;
use serde_json_path_macros::json_path;

fn main() {
    // 创建更复杂的JSON数据结构
    let data: Value = json!({
        "employees": [
            {
                "id": 1,
                "name": "John",
                "department": "IT",
                "skills": ["Rust", "Python", "Java"],
                "salary": 85000,
                "contact": {
                    "email": "john@example.com",
                    "phone": "123-456-7890"
                }
            },
            {
                "id": 2,
                "name": "Alice",
                "department": "HR",
                "skills": ["Communication", "Recruiting"],
                "salary": 75000,
                "contact": {
                    "email": "alice@example.com",
                    "phone": "234-567-8901"
                }
            },
            {
                "id": 3,
                "name": "Bob",
                "department": "IT",
                "skills": ["JavaScript", "TypeScript", "React"],
                "salary": 90000,
                "contact": {
                    "email": "bob@example.com",
                    "phone": "345-678-9012"
                }
            }
        ],
        "company": {
            "name": "Tech Corp",
            "location": "New York",
            "founded": 2010
        }
    });

    // 示例1:获取所有员工姓名
    let names_path = json_path!("$.employees[*].name");
    let names = names_path.query(&data).all();
    println!("所有员工姓名: {:?}", names);

    // 示例2:获取IT部门员工
    let it_employees = json_path!("$.employees[?(@.department == 'IT')]")
        .query(&data)
        .all();
    println!("IT部门员工: {:?}", it_employees);

    // 示例3:获取高薪员工(工资>80000)的邮箱
    let high_salary_emails = json_path!("$.employees[?(@.salary > 80000)].contact.email")
        .query(&data)
        .all();
    println!("高薪员工邮箱: {:?}", high_salary_emails);

    // 示例4:获取所有技能(递归查找)
    let all_skills = json_path!("$..skills[*]")
        .query(&data)
        .all();
    println!("所有技能: {:?}", all_skills);

    // 示例5:使用多重条件查询
    let it_high_salary = json_path!("$.employees[?(@.department == 'IT' && @.salary > 85000)]")
        .query(&data)
        .all();
    println!("IT部门高薪员工: {:?}", it_high_salary);
}

这个完整示例展示了:

  • 基本路径查询
  • 条件过滤
  • 递归查找
  • 多重条件组合查询
  • 嵌套对象访问

通过这些示例,可以全面了解如何使用serde_json_path_macros库来高效地处理和操作JSON数据。


1 回复

Rust JSON路径处理库serde_json_path_macros使用指南

概述

serde_json_path_macros是一个基于serde_jsonjsonpath_lib的Rust宏库,提供了简洁高效的JSON路径查询和操作功能。它允许你使用类似JavaScript的语法来查询和修改JSON数据。

主要特性

  • 简洁的宏语法进行JSON路径查询
  • 支持创建、读取、更新和删除操作
  • 编译时检查路径表达式
  • 高性能的JSON数据处理

安装

Cargo.toml中添加依赖:

[dependencies]
serde_json = "1.0"
serde_json_path_macros = "0.1"

基本使用方法

1. 简单查询

use serde_json::{json, Value};
use serde_json_path_macros::json_path;

fn main() {
    let data = json!({
        "store": {
            "book": [
                { "title": "Rust Programming", "price": 35.99 },
                { "title": "JSON Path Guide", "price": 29.99 }
            ],
            "bicycle": { "color": "red", "price": 399.99 }
        }
    });

    // 查询所有书籍标题
    let titles = json_path!(data, "$.store.book[*].title");
    println!("Book titles: {:?}", titles);
    
    // 查询价格低于100的所有物品
    let cheap_items = json_path!(data, "$..*[?(@.price < 100)]");
    println!("Cheap items: {:?}", cheap_items);
}

2. 修改JSON数据

use serde_json::{json, Value};
use serde_json_path_macros::json_path_mut;

fn main() {
    let mut data = json!({
        "users": [
            { "id": 1, "name": "Alice", "active": false },
            { "id": 2, "name": "Bob", "active": true }
        ]
    });

    // 激活所有用户
    json_path_mut!(data, "$.users[*].active").set(true);
    
    println!("Updated data: {}", data);
}

3. 删除元素

use serde_json::{json, Value};
use serde_json_path_macros::json_path_mut;

fn main() {
    let mut data = json!({
        "products": [
            { "id": "p1", "stock": 0 },
            { "id": "p2", "stock": 42 },
            { "id": "p3", "stock": 0 }
        ]
    });

    // 删除库存为0的产品
    json_path_mut!(data, "$.products[?(@.stock == 0)]").remove();
    
    println!("Filtered products: {}", data);
}

高级用法

1. 链式操作

use serde_json::{json, Value};
use serde_json_path_macros::{json_path, json_path_mut};

fn main() {
    let mut data = json!({
        "departments": {
            "engineering": {
                "employees": [
                    { "name": "Alice", "salary": 80000 },
                    { "name": "Bob", "salary": 75000 }
                ]
            },
            "marketing": {
                "employees": [
                    { "name": "Charlie", "salary": 70000 }
                ]
            }
        }
    });

    // 给所有工程师加薪10%
    json_path_mut!(data, "$.departments.engineering.employees[*].salary")
        .update(|salary: &mut f64| *salary *= 1.1);
    
    // 查询所有员工姓名
    let names = json_path!(data, "$..employees[*].name");
    println!("All employee names: {:?}", names);
}

2. 使用变量构建路径

use serde_json::{json, Value};
use serde_json_path_macros::json_path;

fn main() {
    let data = json!({
        "users": {
            "123": { "name": "Alice", "role": "admin" },
            "456": { "name": "Bob", "role": "user" }
        }
    });

    let user_id = "123";
    let path = format!("$.users.{}", user_id);
    
    // 注意:这种情况下需要使用jsonpath_lib直接操作
    let user = jsonpath_lib::select(&data, &path).unwrap();
    println!("User {}: {:?}", user_id, user);
}

性能提示

  1. 对于频繁的JSON操作,考虑将JSON解析为serde_json::Value后重复使用
  2. 复杂的路径查询可能影响性能,尽量简化路径表达式
  3. 批量操作比多次单独操作更高效

注意事项

  • 路径表达式在编译时检查,错误的语法会导致编译错误
  • 修改操作需要可变引用,确保数据是可变的
  • 对于非常大的JSON文档,考虑使用流式解析器替代

这个库为Rust中的JSON处理提供了强大而灵活的工具,特别适合需要复杂JSON操作的场景。

完整示例代码

// 完整示例:使用serde_json_path_macros进行复杂JSON操作
use serde_json::{json, Value};
use serde_json_path_macros::{json_path, json_path_mut};

fn main() {
    // 1. 创建复杂JSON数据结构
    let mut company_data = json!({
        "company": {
            "name": "Tech Corp",
            "departments": {
                "engineering": {
                    "team": "Rust",
                    "members": [
                        {"id": 1, "name": "Alice", "skills": ["Rust", "C++"], "salary": 90000},
                        {"id": 2, "name": "Bob", "skills": ["Rust", "Python"], "salary": 85000}
                    ]
                },
                "design": {
                    "team": "UI/UX",
                    "members": [
                        {"id": 3, "name": "Charlie", "skills": ["Figma", "Photoshop"], "salary": 75000}
                    ]
                }
            },
            "projects": [
                {"id": "p1", "name": "Rust Microservices", "status": "active"},
                {"id": "p2", "name": "Web Redesign", "status": "pending"}
            ]
        }
    });

    // 2. 查询操作示例
    // 查询所有工程师姓名
    let engineer_names = json_path!(company_data, "$.company.departments.engineering.members[*].name");
    println!("Engineer names: {:?}", engineer_names);

    // 查询所有活跃项目
    let active_projects = json_path!(company_data, "$.company.projects[?(@.status == 'active')]");
    println!("Active projects: {:?}", active_projects);

    // 3. 修改操作示例
    // 给所有工程师加薪5%
    json_path_mut!(company_data, "$.company.departments.engineering.members[*].salary")
        .update(|salary: &mut f64| *salary *= 1.05);

    // 激活所有pending状态的项目
    json_path_mut!(company_data, "$.company.projects[?(@.status == 'pending')].status")
        .set("active");

    // 4. 删除操作示例
    // 删除技能中不包含Rust的工程师
    json_path_mut!(company_data, "$.company.departments.engineering.members[?(!@.skills.contains('Rust'))]")
        .remove();

    // 5. 最终数据输出
    println!("Final company data:\n{}", company_data);

    // 6. 使用变量构建路径查询
    let project_id = "p1";
    let project_path = format!("$.company.projects[?(@.id == '{}')]", project_id);
    let project = jsonpath_lib::select(&company_data, &project_path).unwrap();
    println!("Project {} details: {:?}", project_id, project);
}

这个完整示例展示了:

  1. 创建复杂的嵌套JSON数据结构
  2. 使用各种查询方式获取数据
  3. 对数据进行修改和更新
  4. 根据条件删除数据元素
  5. 使用变量构建动态路径查询

运行此代码前请确保已正确添加依赖项。这个示例综合展示了serde_json_path_macros在实际应用中的强大功能。

回到顶部