5个版本 (3个破坏性更新)
0.4.0 | 2024年7月30日 |
---|---|
0.3.0 | 2024年7月28日 |
0.2.0 | 2024年6月27日 |
0.1.1 | 2024年6月26日 |
0.1.0 | 2024年6月25日 |
#2 in #params
每月308次下载
36KB
456 行
OData v4参数解析库
此库为OData v4 $filter
表达式提供解析器。它将这些表达式转换为抽象语法树(AST),以便进行进一步处理和评估。解析器支持广泛的逻辑运算符、比较运算符、函数调用和嵌套表达式,使其非常适合复杂的查询需求。
请注意,这是一个持续开发的项目。下一版本将添加支持和不支持的功能组件的完整列表。
功能
- 逻辑运算符:
and
,or
,not
- 比较运算符:
eq
,ne
,gt
,lt
,ge
,le
- 函数调用: 例如
startswith
,endswith
,contains
,concat
- 分组: 括号内的嵌套表达式
- 数据类型: 字符串、数字、布尔值、日期、时间、带时区的日期时间
尚未实现
- lambda函数:
any
,all
- 参数别名:
@something
has
运算符
数据类型
该库在表达式中支持以下数据类型
- 字符串: 用单引号括起来
'example'
- 数字: 整数和小数
123
,45.67
- UUID: UUIDs
da820b39-5ad2-4441-b664-c902dbd377d8
- 布尔值:
true
,false
- 时间: ISO 8601格式
HH:MM:SS
- 日期: ISO 8601格式
YYYY-MM-DD
- 日期时间:ISO 8601 格式,带有时区
YYYY-MM-DDTHH:MM:SSZ
测试
该库包含一组由AI生成的大部分测试,用于捕获回归。测试文件包含多个示例,以展示如何使用库以及预期输出。
可以使用以下命令运行测试
cargo test
安装
要将此库添加到您的项目中,请将以下内容添加到您的 Cargo.toml
[dependencies]
odata-params = "0.2.0"
或者运行 cargo add odata-params
。
示例
以下是如何解析简单过滤器表达式的示例
use odata_params::filters::{parse_str, to_query_string};
fn main() {
// Convert a string query to Expr AST.
let filter = "name eq 'John' and isActive eq true";
let result = parse_str(filter).expect("valid filter tree");
println!("{:#?}", result);
// Convert Expr AST into a string query.
let query_string = to_query_string(&result).expect("valid query string");
println!("{}", query_string);
}
支持的表达式
逻辑运算符
use odata_params::filters::parse_str;
let filter = "name eq 'John' or isActive eq true";
let result = parse_str(filter).expect("valid filter tree");
// Expected Expr structure:
// Expr::Or(
// Box::new(Expr::Compare(
// Box::new(Expr::Identifier("name".to_owned())),
// CompareOperator::Equal,
// Box::new(Expr::Value(Value::String("John".to_owned()))),
// )),
// Box::new(Expr::Compare(
// Box::new(Expr::Identifier("isActive".to_owned())),
// CompareOperator::Equal,
// Box::new(Expr::Value(Value::Bool(true))),
// )),
// )
比较运算符
use odata_params::filters::parse_str;
let filter = "price lt 99.99";
let result = parse_str(filter).expect("valid filter tree");
// Expected Expr structure:
// Expr::Compare(
// Box::new(Expr::Identifier("price".to_owned())),
// CompareOperator::LessThan,
// Box::new(Expr::Value(Value::Number(BigDecimal::from_str("99.99").unwrap()))),
// )
函数调用
use odata_params::filters::parse_str;
let filter = "endswith(name, 'Smith')";
let result = parse_str(filter).expect("valid filter tree");
// Expected Expr structure:
// Expr::Function(
// "endswith".to_owned(),
// vec![
// Expr::Identifier("name".to_owned()),
// Expr::Value(Value::String("Smith".to_owned()))
// ]
// )
高级用法
嵌套分组
use odata_params::filters::parse_str;
let filter = "((name eq 'John' and isActive eq true) or (age gt 30 and age lt 50))";
let result = parse_str(filter).expect("valid filter tree");
// Expected Expr structure:
// Expr::Or(
// Box::new(Expr::And(
// Box::new(Expr::Compare(
// Box::new(Expr::Identifier("name".to_owned())),
// CompareOperator::Equal,
// Box::new(Expr::Value(Value::String("John".to_owned()))),
// )),
// Box::new(Expr::Compare(
// Box::new(Expr::Identifier("isActive".to_owned())),
// CompareOperator::Equal,
// Box::new(Expr::Value(Value::Bool(true))),
// )),
// )),
// Box::new(Expr::And(
// Box::new(Expr::Compare(
// Box::new(Expr::Identifier("age".to_owned())),
// CompareOperator::GreaterThan,
// Box::new(Expr::Value(Value::Number(BigDecimal::from_str("30").unwrap()))),
// )),
// Box::new(Expr::Compare(
// Box::new(Expr::Identifier("age".to_owned())),
// CompareOperator::LessThan,
// Box::new(Expr::Value(Value::Number(BigDecimal::from_str("50").unwrap()))),
// )),
// )),
// )
带有比较的函数
use odata_params::filters::parse_str;
let filter = "concat(concat(city, ', '), country) eq 'Berlin, Germany'";
let result = parse_str(filter).expect("valid filter tree");
// Expected Expr structure:
// Expr::Compare(
// Box::new(Expr::Function(
// "concat".to_owned(),
// vec![
// Expr::Function(
// "concat".to_owned(),
// vec![
// Expr::Identifier("city".to_owned()),
// Expr::Value(Value::String(", ".to_owned()))
// ]
// ),
// Expr::Identifier("country".to_owned())
// ]
// )),
// CompareOperator::Equal,
// Box::new(Expr::Value(Value::String("Berlin, Germany".to_owned())))
// )
依赖项
~2.9–4MB
~72K SLoC