updates

This commit is contained in:
JMARyA 2025-05-06 23:43:23 +02:00
parent 77185abd6a
commit b1ad069731
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
4 changed files with 114 additions and 8 deletions

View file

@ -40,10 +40,10 @@ This filter would match all of these objects:
```
but not:
```json
{ "key": "Lol"}
{ "key": "lol"}
```
## Operators
## Logical Operators
### `$and`
Chain multiple filters together. All must evaluate to `true`
```json
@ -72,6 +72,7 @@ Inverts the result of the nested filter expression.
{ "$not": { "key": "value" }}
```
## Comparison Operators
### `$lt` & `$lte`
Evaluates to `true` if the value is less than or less than equal the specified value.
```json
@ -90,7 +91,10 @@ Evaluates to `true` if the value is not equal to the specified value.
{ "key": { "$ne": "value" }}
```
### `$in`
> **Note**: The `$eq` operator is implicit. Example: `{ "key": "value" }`
## Array / Object Operators
### `$in` & `$contains`
Evaluates to `true` if the value exists in the specified array.
```json
{ "array": { "$in": "value" }}
@ -115,12 +119,20 @@ Evaluates to `true` if the array length matches the specified value
{ "array": { "$size": 5 }}
```
## Text Operators
### `$regex`
Evaluates to `true` if the value matches the regular expression pattern.
```json
{ "key": { "$regex": "^regex" }}
```
### `$contains`
Evaluates to `true` if the value contains the text.
```json
{ "key": { "$contains": "text" }}
```
## Misc Operators
### `$type`
Evaluates to `true` if the value matches the specified type.
```json
@ -130,4 +142,11 @@ Evaluates to `true` if the value matches the specified type.
{ "key": { "$type": "object" }}
{ "key": { "$type": "array" }}
{ "key": { "$type": "boolean" }}
```
```
### `$range`
Evaluates to `true` if the value is within the specified range. This operator is actually just syntactic sugar for `let filter = json!({"$and": [{"key": {"$gte": x}}, {"key": {"$lte": y}}]});`.
```json
{"key": { "$range": [x, y] }}
```

View file

@ -2,7 +2,8 @@ use jsonfilter::{try_matches, FilterError};
use serde_json::{json, Value};
fn main() {
let filter = json!({"$and": [{"age": {"$gte": 18}}, {"age": {"$lte": 30}}]});
let filter = json!({"age": { "$range": [18, 30] }}); // same as:
// let filter = json!({"$and": [{"age": {"$gte": 18}}, {"age": {"$lte": 30}}]});
let obj1 = json!({"name": "John Doe", "age": 25});
let obj2 = json!({"name": "Alice Smith", "age": 35});

View file

@ -402,10 +402,18 @@ fn match_operator(
}
return Err(FilterError::KeyNotFound);
}
"$in" => {
"$in" | "$contains" => {
if let Some(valb) = obj.get(key) {
if let serde_json::Value::Array(list) = valb {
return Ok(list.iter().any(|x| x == op_arg));
match valb {
serde_json::Value::String(str) => {
if let serde_json::Value::String(op_arg) = op_arg {
return Ok(str.contains(op_arg));
}
}
serde_json::Value::Array(list) => {
return Ok(list.iter().any(|x| x == op_arg));
}
_ => {}
}
return Err(FilterError::InvalidFilter);
}
@ -487,6 +495,20 @@ fn match_operator(
}
return Err(FilterError::KeyNotFound);
}
"$range" => {
let x = op_arg.as_array().unwrap().get(0).unwrap();
let y = op_arg.as_array().unwrap().get(1).unwrap();
return match_operator(
&json!({
"$and": [
{ key: { "$gte": x}},
{ key: { "$lte": y}}
]
}),
raw_obj,
key,
);
}
_ => {
if op.starts_with('$') {
return Err(FilterError::UnknownOperator);

View file

@ -109,6 +109,70 @@ mod tests {
));
}
#[test]
fn text_contains() {
assert!(matches(
&json!({
"key": {
"$contains": "world"
}
}),
&json!({
"key": "hello world"
})
));
}
#[test]
fn range_op() {
assert!(matches(
&json!({"key": { "$range": [18, 30] }}),
&json!({
"key": 20
})
));
assert!(!matches(
&json!({"key": { "$range": [18, 30] }}),
&json!({
"key": 15
})
));
assert!(!matches(
&json!({"key": { "$range": [18, 30] }}),
&json!({
"key": 40
})
));
}
#[test]
fn in_array_contains() {
assert!(matches(
&json!({
"key": {
"$contains": 3
}
}),
&json!({
"key": [1,2,3,4,5]
})
));
assert!(matches(
&json!({
"$not": {
"key": {
"$contains": 3
}}
}),
&json!({
"key": [1,2,4,5]
})
));
}
#[test]
fn in_array() {
assert!(matches(