Crates.io | odata-params |
lib.rs | odata-params |
version | 0.4.0 |
source | src |
created_at | 2024-06-25 04:14:53.039211 |
updated_at | 2024-07-30 01:46:13.95092 |
description | OData v4 query parameters parsers for handling paginated requests. |
homepage | |
repository | https://github.com/JenChampagne/odata-params |
max_upload_size | |
id | 1282971 |
size | 76,045 |
This library provides a parser for OData v4 $filter
expressions.
It converts these expressions into an Abstract Syntax Tree (AST),
allowing for further processing and evaluation. The parser supports
a wide range of logical operators, comparison operators, function calls,
and nested expressions, making it highly versatile for complex querying needs.
Note that this is a work in progress. A full list of specification components that are supported and not supported will be added in the next release.
and
, or
, not
eq
, ne
, gt
, lt
, ge
, le
startswith
, endswith
, contains
, concat
any
, all
@something
has
OperatorThe library supports the following data types in expressions:
'example'
123
, 45.67
da820b39-5ad2-4441-b664-c902dbd377d8
true
, false
HH:MM:SS
YYYY-MM-DD
YYYY-MM-DDTHH:MM:SSZ
The library includes a set of tests mostly generated by AI to catch regressions. The test files contain numerous examples to see how the library can be used and what outputs to expect.
You can run the tests using the following command:
cargo test
To add this library to your project, add the following to your Cargo.toml
:
[dependencies]
odata-params = "0.2.0"
Or run cargo add odata-params
.
Here is an example of how to parse a simple filter expression:
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())))
// )