mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-07-17 16:32:00 +00:00
Compare commits
9 Commits
v0.2.4
...
bugs/multi
Author | SHA1 | Date | |
---|---|---|---|
|
a6f742e3ad | ||
|
6f20013076 | ||
|
218321a4bd | ||
|
d855c17899 | ||
|
4919a03c6b | ||
|
7a07bc7744 | ||
|
32eef3f7c7 | ||
|
b736c962d2 | ||
|
accd08139f |
12
.idea/runConfigurations/filter.xml
generated
12
.idea/runConfigurations/filter.xml
generated
@@ -1,12 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="filter" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="test --package jsonpath_lib --test filter """ />
|
||||
<option name="allFeatures" value="false" />
|
||||
<option name="nocapture" value="false" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
12
.idea/runConfigurations/lib.xml
generated
12
.idea/runConfigurations/lib.xml
generated
@@ -1,12 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="lib" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="test --package jsonpath_lib --test lib """ />
|
||||
<option name="allFeatures" value="false" />
|
||||
<option name="nocapture" value="false" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
12
.idea/runConfigurations/mutable.xml
generated
12
.idea/runConfigurations/mutable.xml
generated
@@ -1,12 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="mutable" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="test --package jsonpath_lib --test mutable """ />
|
||||
<option name="allFeatures" value="false" />
|
||||
<option name="nocapture" value="false" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
12
.idea/runConfigurations/readme.xml
generated
12
.idea/runConfigurations/readme.xml
generated
@@ -1,12 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="readme" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="test --package jsonpath_lib --test readme """ />
|
||||
<option name="allFeatures" value="false" />
|
||||
<option name="nocapture" value="false" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
10
.travis.yml
10
.travis.yml
@@ -24,15 +24,9 @@ matrix:
|
||||
before_script:
|
||||
- rustup component add clippy
|
||||
script:
|
||||
- cargo clean
|
||||
- cargo clippy -- -D warnings
|
||||
- cargo build --verbose --all
|
||||
- cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity
|
||||
- cargo test --verbose --all
|
||||
- cd wasm && cargo clippy -- -D warnings -A clippy::suspicious_else_formatting
|
||||
- cd ../../
|
||||
- ./clippy.sh
|
||||
after_success: |
|
||||
cargo tarpaulin --exclude-files nodejs wasm parser/mod.rs --out Xml
|
||||
cargo tarpaulin --exclude-files wasm parser/mod.rs --out Xml
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
- rust: stable
|
||||
os: osx
|
||||
|
11
clippy.sh
Executable file
11
clippy.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cargo clean
|
||||
cargo clippy -- -D warnings
|
||||
cargo build --verbose --all
|
||||
cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity
|
||||
cargo test --verbose --all
|
||||
cd wasm && cargo clippy -- -D warnings -A clippy::suspicious_else_formatting
|
||||
cd ../
|
@@ -13,8 +13,8 @@ mod utils {
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn string_to_num<F, S: FromStr>(string: &str, msg_handler: F) -> Result<S, String>
|
||||
where
|
||||
F: Fn() -> String,
|
||||
where
|
||||
F: Fn() -> String,
|
||||
{
|
||||
match string.parse() {
|
||||
Ok(n) => Ok(n),
|
||||
@@ -209,7 +209,8 @@ impl Parser {
|
||||
|
||||
fn array_keys(tokenizer: &mut TokenReader, first_key: String) -> ParseResult<Node> {
|
||||
let mut keys = vec![first_key];
|
||||
while tokenizer.peek_is(COMMA) {
|
||||
|
||||
while let Ok(Token::Comma(_)) = tokenizer.peek_token() {
|
||||
Self::eat_token(tokenizer);
|
||||
Self::eat_whitespace(tokenizer);
|
||||
|
||||
@@ -230,7 +231,7 @@ impl Parser {
|
||||
debug!("#array_quote_value");
|
||||
match tokenizer.next_token() {
|
||||
Ok(Token::SingleQuoted(_, val)) | Ok(Token::DoubleQuoted(_, val)) => {
|
||||
if tokenizer.peek_is(COMMA) {
|
||||
if let Ok(Token::Comma(_)) = tokenizer.peek_token() {
|
||||
Self::array_keys(tokenizer, val)
|
||||
} else {
|
||||
Ok(Self::node(ParseToken::Key(val)))
|
||||
@@ -529,41 +530,35 @@ impl Parser {
|
||||
fn term(tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||
debug!("#term");
|
||||
|
||||
if tokenizer.peek_is(AT) {
|
||||
Self::eat_token(tokenizer);
|
||||
let node = Self::node(ParseToken::Relative);
|
||||
match tokenizer.peek_token() {
|
||||
Ok(Token::At(_)) => {
|
||||
Self::eat_token(tokenizer);
|
||||
let node = Self::node(ParseToken::Relative);
|
||||
|
||||
return match tokenizer.peek_token() {
|
||||
Ok(Token::Whitespace(_, _)) => {
|
||||
Self::eat_whitespace(tokenizer);
|
||||
Ok(node)
|
||||
match tokenizer.peek_token() {
|
||||
Ok(Token::Whitespace(_, _)) => {
|
||||
Self::eat_whitespace(tokenizer);
|
||||
Ok(node)
|
||||
}
|
||||
_ => Self::paths(node, tokenizer),
|
||||
}
|
||||
_ => Self::paths(node, tokenizer),
|
||||
};
|
||||
}
|
||||
Ok(Token::Absolute(_)) => {
|
||||
Self::json_path(tokenizer)
|
||||
},
|
||||
Ok(Token::DoubleQuoted(_, _)) | Ok(Token::SingleQuoted(_, _)) => {
|
||||
Self::array_quote_value(tokenizer)
|
||||
},
|
||||
Ok(Token::Key(_, key)) => {
|
||||
match key.as_bytes()[0] {
|
||||
b'-' | b'0'..=b'9' => Self::term_num(tokenizer),
|
||||
_ => Self::boolean(tokenizer),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Err(tokenizer.err_msg())
|
||||
}
|
||||
}
|
||||
|
||||
if tokenizer.peek_is(ABSOLUTE) {
|
||||
return Self::json_path(tokenizer);
|
||||
}
|
||||
|
||||
if tokenizer.peek_is(DOUBLE_QUOTE) || tokenizer.peek_is(SINGLE_QUOTE) {
|
||||
return Self::array_quote_value(tokenizer);
|
||||
}
|
||||
|
||||
if tokenizer.peek_is(KEY) {
|
||||
let key = if let Ok(Token::Key(_, k)) = tokenizer.peek_token() {
|
||||
k.clone()
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
return match key.as_bytes()[0] {
|
||||
b'-' | b'0'..=b'9' => Self::term_num(tokenizer),
|
||||
_ => Self::boolean(tokenizer),
|
||||
};
|
||||
}
|
||||
|
||||
Err(tokenizer.err_msg())
|
||||
}
|
||||
|
||||
fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||
@@ -610,7 +605,7 @@ impl Parser {
|
||||
fn close_token(ret: Node, token: Token, tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||
debug!("#close_token");
|
||||
match tokenizer.next_token() {
|
||||
Ok(ref t) if t.partial_eq(token) => Ok(ret),
|
||||
Ok(ref t) if t.is_match_token_type(token) => Ok(ret),
|
||||
_ => Err(tokenizer.err_msg()),
|
||||
}
|
||||
}
|
||||
|
@@ -2,30 +2,6 @@ use std::result::Result;
|
||||
|
||||
use super::path_reader::{PathReader, ReaderError};
|
||||
|
||||
pub const ABSOLUTE: &str = "$";
|
||||
pub const DOT: &str = ".";
|
||||
pub const AT: &str = "@";
|
||||
pub const OPEN_ARRAY: &str = "[";
|
||||
pub const CLOSE_ARRAY: &str = "]";
|
||||
pub const ASTERISK: &str = "*";
|
||||
pub const QUESTION: &str = "?";
|
||||
pub const COMMA: &str = ",";
|
||||
pub const SPLIT: &str = ":";
|
||||
pub const OPEN_PARENTHESIS: &str = "(";
|
||||
pub const CLOSE_PARENTHESIS: &str = ")";
|
||||
pub const KEY: &str = "Key";
|
||||
pub const DOUBLE_QUOTE: &str = "\"";
|
||||
pub const SINGLE_QUOTE: &str = "'";
|
||||
pub const EQUAL: &str = "==";
|
||||
pub const GREATER_OR_EQUAL: &str = ">=";
|
||||
pub const GREATER: &str = ">";
|
||||
pub const LITTLE: &str = "<";
|
||||
pub const LITTLE_OR_EQUAL: &str = "<=";
|
||||
pub const NOT_EQUAL: &str = "!=";
|
||||
pub const AND: &str = "&&";
|
||||
pub const OR: &str = "||";
|
||||
pub const WHITESPACE: &str = " ";
|
||||
|
||||
const CH_DOLLA: char = '$';
|
||||
const CH_DOT: char = '.';
|
||||
const CH_ASTERISK: char = '*';
|
||||
@@ -86,61 +62,104 @@ pub enum Token {
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn partial_eq(&self, other: Token) -> bool {
|
||||
self.to_simple() == other.to_simple()
|
||||
}
|
||||
|
||||
pub fn simple_eq(&self, str_token: &str) -> bool {
|
||||
self.to_simple() == str_token
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn to_simple(&self) -> &'static str {
|
||||
pub fn is_match_token_type(&self, other: Token) -> bool {
|
||||
match self {
|
||||
Token::Absolute(_) => ABSOLUTE,
|
||||
Token::Dot(_) => DOT,
|
||||
Token::At(_) => AT,
|
||||
Token::OpenArray(_) => OPEN_ARRAY,
|
||||
Token::CloseArray(_) => CLOSE_ARRAY,
|
||||
Token::Asterisk(_) => ASTERISK,
|
||||
Token::Question(_) => QUESTION,
|
||||
Token::Comma(_) => COMMA,
|
||||
Token::Split(_) => SPLIT,
|
||||
Token::OpenParenthesis(_) => OPEN_PARENTHESIS,
|
||||
Token::CloseParenthesis(_) => CLOSE_PARENTHESIS,
|
||||
Token::Key(_, _) => KEY,
|
||||
Token::DoubleQuoted(_, _) => DOUBLE_QUOTE,
|
||||
Token::SingleQuoted(_, _) => SINGLE_QUOTE,
|
||||
Token::Equal(_) => EQUAL,
|
||||
Token::GreaterOrEqual(_) => GREATER_OR_EQUAL,
|
||||
Token::Greater(_) => GREATER,
|
||||
Token::Little(_) => LITTLE,
|
||||
Token::LittleOrEqual(_) => LITTLE_OR_EQUAL,
|
||||
Token::NotEqual(_) => NOT_EQUAL,
|
||||
Token::And(_) => AND,
|
||||
Token::Or(_) => OR,
|
||||
Token::Whitespace(_, _) => WHITESPACE,
|
||||
Token::Absolute(_) => match other {
|
||||
Token::Absolute(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Dot(_) => match other {
|
||||
Token::Dot(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::At(_) => match other {
|
||||
Token::At(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::OpenArray(_) => match other {
|
||||
Token::OpenArray(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::CloseArray(_) => match other {
|
||||
Token::CloseArray(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Asterisk(_) => match other {
|
||||
Token::Asterisk(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Question(_) => match other {
|
||||
Token::Question(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Comma(_) => match other {
|
||||
Token::Comma(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Split(_) => match other {
|
||||
Token::Split(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::OpenParenthesis(_) => match other {
|
||||
Token::OpenParenthesis(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::CloseParenthesis(_) => match other {
|
||||
Token::CloseParenthesis(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Key(_, _) => match other {
|
||||
Token::Key(_, _) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::DoubleQuoted(_, _) => match other {
|
||||
Token::DoubleQuoted(_, _) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::SingleQuoted(_, _) => match other {
|
||||
Token::SingleQuoted(_, _) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Equal(_) => match other {
|
||||
Token::Equal(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::GreaterOrEqual(_) => match other {
|
||||
Token::GreaterOrEqual(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Greater(_) => match other {
|
||||
Token::Greater(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Little(_) => match other {
|
||||
Token::Little(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::LittleOrEqual(_) => match other {
|
||||
Token::LittleOrEqual(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::NotEqual(_) => match other {
|
||||
Token::NotEqual(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::And(_) => match other {
|
||||
Token::And(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Or(_) => match other {
|
||||
Token::Or(_) => true,
|
||||
_ => false
|
||||
},
|
||||
Token::Whitespace(_, _) => match other {
|
||||
Token::Whitespace(_, _) => true,
|
||||
_ => false
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn simple_matched_token(ch: char, pos: usize) -> Option<Token> {
|
||||
match ch {
|
||||
CH_DOLLA => Some(Token::Absolute(pos)),
|
||||
CH_DOT => Some(Token::Dot(pos)),
|
||||
CH_ASTERISK => Some(Token::Asterisk(pos)),
|
||||
CH_LARRAY => Some(Token::OpenArray(pos)),
|
||||
CH_RARRAY => Some(Token::CloseArray(pos)),
|
||||
CH_LPAREN => Some(Token::OpenParenthesis(pos)),
|
||||
CH_RPAREN => Some(Token::CloseParenthesis(pos)),
|
||||
CH_AT => Some(Token::At(pos)),
|
||||
CH_QUESTION => Some(Token::Question(pos)),
|
||||
CH_COMMA => Some(Token::Comma(pos)),
|
||||
CH_SEMICOLON => Some(Token::Split(pos)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tokenizer<'a> {
|
||||
input: PathReader<'a>,
|
||||
}
|
||||
@@ -261,17 +280,25 @@ impl<'a> Tokenizer<'a> {
|
||||
}
|
||||
|
||||
fn other(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> {
|
||||
let fun = |c: &char| match simple_matched_token(*c, pos) {
|
||||
Some(_) => false,
|
||||
_ if c == &CH_LITTLE
|
||||
|| c == &CH_GREATER
|
||||
|| c == &CH_EQUAL
|
||||
|| c == &CH_AMPERSAND
|
||||
|| c == &CH_PIPE
|
||||
|| c == &CH_EXCLAMATION =>
|
||||
{
|
||||
false
|
||||
}
|
||||
let fun = |c: &char| match c {
|
||||
&CH_DOLLA
|
||||
| &CH_DOT
|
||||
| &CH_ASTERISK
|
||||
| &CH_LARRAY
|
||||
| &CH_RARRAY
|
||||
| &CH_LPAREN
|
||||
| &CH_RPAREN
|
||||
| &CH_AT
|
||||
| &CH_QUESTION
|
||||
| &CH_COMMA
|
||||
| &CH_SEMICOLON
|
||||
| &CH_LITTLE
|
||||
| &CH_GREATER
|
||||
| &CH_EQUAL
|
||||
| &CH_AMPERSAND
|
||||
| &CH_PIPE
|
||||
| &CH_EXCLAMATION
|
||||
=> false,
|
||||
_ => !c.is_whitespace(),
|
||||
};
|
||||
let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?;
|
||||
@@ -281,20 +308,28 @@ impl<'a> Tokenizer<'a> {
|
||||
|
||||
pub fn next_token(&mut self) -> Result<Token, TokenError> {
|
||||
let (pos, ch) = self.input.next_char().map_err(to_token_error)?;
|
||||
match simple_matched_token(ch, pos) {
|
||||
Some(t) => Ok(t),
|
||||
None => match ch {
|
||||
CH_SINGLE_QUOTE => self.single_quote(pos, ch),
|
||||
CH_DOUBLE_QUOTE => self.double_quote(pos, ch),
|
||||
CH_EQUAL => self.equal(pos, ch),
|
||||
CH_GREATER => self.greater(pos, ch),
|
||||
CH_LITTLE => self.little(pos, ch),
|
||||
CH_AMPERSAND => self.and(pos, ch),
|
||||
CH_PIPE => self.or(pos, ch),
|
||||
CH_EXCLAMATION => self.not_equal(pos, ch),
|
||||
_ if ch.is_whitespace() => self.whitespace(pos, ch),
|
||||
_ => self.other(pos, ch),
|
||||
},
|
||||
match ch {
|
||||
CH_DOLLA => Ok(Token::Absolute(pos)),
|
||||
CH_DOT => Ok(Token::Dot(pos)),
|
||||
CH_ASTERISK => Ok(Token::Asterisk(pos)),
|
||||
CH_LARRAY => Ok(Token::OpenArray(pos)),
|
||||
CH_RARRAY => Ok(Token::CloseArray(pos)),
|
||||
CH_LPAREN => Ok(Token::OpenParenthesis(pos)),
|
||||
CH_RPAREN => Ok(Token::CloseParenthesis(pos)),
|
||||
CH_AT => Ok(Token::At(pos)),
|
||||
CH_QUESTION => Ok(Token::Question(pos)),
|
||||
CH_COMMA => Ok(Token::Comma(pos)),
|
||||
CH_SEMICOLON => Ok(Token::Split(pos)),
|
||||
CH_SINGLE_QUOTE => self.single_quote(pos, ch),
|
||||
CH_DOUBLE_QUOTE => self.double_quote(pos, ch),
|
||||
CH_EQUAL => self.equal(pos, ch),
|
||||
CH_GREATER => self.greater(pos, ch),
|
||||
CH_LITTLE => self.little(pos, ch),
|
||||
CH_AMPERSAND => self.and(pos, ch),
|
||||
CH_PIPE => self.or(pos, ch),
|
||||
CH_EXCLAMATION => self.not_equal(pos, ch),
|
||||
_ if ch.is_whitespace() => self.whitespace(pos, ch),
|
||||
_ => self.other(pos, ch),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,13 +368,6 @@ impl<'a> TokenReader<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek_is(&self, simple_token: &str) -> bool {
|
||||
match self.peek_token() {
|
||||
Ok(t) => t.simple_eq(simple_token),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek_token(&self) -> Result<&Token, TokenError> {
|
||||
match self.tokens.last() {
|
||||
Some((_, t)) => {
|
||||
|
@@ -286,7 +286,26 @@ impl<'a> ExprTerm<'a> {
|
||||
if ret.is_empty() {
|
||||
ExprTerm::Bool(cmp_fn.default())
|
||||
} else if let Some(rel) = rel {
|
||||
ExprTerm::Json(Some(rel.to_vec()), None, ret)
|
||||
if let ExprTerm::Json(_, _, _) = &other {
|
||||
ExprTerm::Json(Some(rel.to_vec()), None, ret)
|
||||
} else {
|
||||
let mut tmp = Vec::new();
|
||||
for rel_value in rel {
|
||||
match rel_value {
|
||||
Value::Object(map) => {
|
||||
for map_value in map.values() {
|
||||
for result_value in &ret {
|
||||
if map_value.eq(*result_value) {
|
||||
tmp.push(*rel_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ExprTerm::Json(Some(tmp), None, ret)
|
||||
}
|
||||
} else {
|
||||
ExprTerm::Json(None, None, ret)
|
||||
}
|
||||
@@ -439,9 +458,9 @@ fn walk<'a, F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F)
|
||||
|
||||
fn abs_index(n: isize, len: usize) -> usize {
|
||||
if n < 0_isize {
|
||||
(n + len as isize) as usize
|
||||
(n + len as isize).max(0) as usize
|
||||
} else {
|
||||
n as usize
|
||||
n.min(len as isize) as usize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,17 +729,37 @@ impl<'a, 'b> Selector<'a, 'b> {
|
||||
}
|
||||
|
||||
fn next_from_current_with_num(&mut self, index: f64) {
|
||||
fn _collect<'a>(tmp: &mut Vec<&'a Value>, vec: &'a [Value], index: f64) {
|
||||
let index = abs_index(index as isize, vec.len());
|
||||
if let Some(v) = vec.get(index) {
|
||||
tmp.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(current) = self.current.take() {
|
||||
let mut tmp = Vec::new();
|
||||
for c in current {
|
||||
if let Value::Array(vec) = c {
|
||||
let index = abs_index(index as isize, vec.len());
|
||||
if let Some(v) = c.get(index) {
|
||||
tmp.push(v);
|
||||
match c {
|
||||
Value::Object(map) => {
|
||||
for k in map.keys() {
|
||||
if let Some(Value::Array(vec)) = map.get(k) {
|
||||
_collect(&mut tmp, vec, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Array(vec) => {
|
||||
_collect(&mut tmp, vec, index);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
self.current = Some(tmp);
|
||||
|
||||
if tmp.is_empty() {
|
||||
self.terms.pop();
|
||||
self.current = Some(vec![&Value::Null]);
|
||||
} else {
|
||||
self.current = Some(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
debug!(
|
||||
@@ -729,27 +768,6 @@ impl<'a, 'b> Selector<'a, 'b> {
|
||||
);
|
||||
}
|
||||
|
||||
fn next_from_current_with_str(&mut self, keys: &[String]) {
|
||||
if let Some(current) = self.current.take() {
|
||||
let mut tmp = Vec::new();
|
||||
for c in current {
|
||||
if let Value::Object(map) = c {
|
||||
for key in keys {
|
||||
if let Some(v) = map.get(key) {
|
||||
tmp.push(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.current = Some(tmp);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"next_from_current_with_str : {:?}, {:?}",
|
||||
keys, self.current
|
||||
);
|
||||
}
|
||||
|
||||
fn next_all_from_current(&mut self) {
|
||||
if let Some(current) = self.current.take() {
|
||||
let mut tmp = Vec::new();
|
||||
@@ -774,6 +792,32 @@ impl<'a, 'b> Selector<'a, 'b> {
|
||||
debug!("next_all_from_current : {:?}", self.current);
|
||||
}
|
||||
|
||||
fn next_from_current_with_str(&mut self, keys: &[String]) {
|
||||
if let Some(current) = self.current.take() {
|
||||
let mut tmp = Vec::new();
|
||||
for c in current {
|
||||
if let Value::Object(map) = c {
|
||||
for key in keys {
|
||||
if let Some(v) = map.get(key) {
|
||||
tmp.push(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tmp.is_empty() {
|
||||
self.current = Some(vec![&Value::Null]);
|
||||
} else {
|
||||
self.current = Some(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
debug!(
|
||||
"next_from_current_with_str : {:?}, {:?}",
|
||||
keys, self.current
|
||||
);
|
||||
}
|
||||
|
||||
fn all_from_current(&mut self) {
|
||||
if let Some(current) = self.current.take() {
|
||||
let mut tmp = Vec::new();
|
||||
|
218
tests/array_filter.rs
Normal file
218
tests/array_filter.rs
Normal file
@@ -0,0 +1,218 @@
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use common::{read_json, select_and_then_compare, setup};
|
||||
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn array_range_default() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[1, 2]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_all() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[ : ]",
|
||||
json!(["first", "second"]),
|
||||
json!(["first", "second"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_all() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[::]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_only_step_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[::2]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "third", "fifth"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_only_start_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[1::]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["second", "third", "forth", "fifth"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_empty_step_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[1:2:]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["second"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_empty_end_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[1::2]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["second", "forth"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_by_1() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[0:3:1]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "second", "third"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_step_by_2() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[0:3:2]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "third"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_only_negative_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[-4:]",
|
||||
json!(["first", "second", "third"]),
|
||||
json!(["first", "second", "third"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_only_end_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[:4]",
|
||||
json!(["first", "second", "third"]),
|
||||
json!(["first", "second", "third"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_only_from_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[1: ]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_range_only_nagative_end_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[:-2]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{"id": 0, "name": "Millicent Norman"}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..friends[2].name",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["Gray Berry", "Gray Berry"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_all_index() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..friends[*].name",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
"Vincent Cannon",
|
||||
"Gray Berry",
|
||||
"Millicent Norman",
|
||||
"Vincent Cannon",
|
||||
"Gray Berry"
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_all_and_then_key() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$['school']['friends'][*].['name']",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_index_and_then_key() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$['school']['friends'][0].['name']",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["Millicent Norman"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_multiple_key() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.["eyeColor", "name"]"#,
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["blue", "Leonor Herman"]),
|
||||
);
|
||||
}
|
652
tests/filter.rs
652
tests/filter.rs
@@ -1,609 +1,10 @@
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
use common::{read_json, select_and_then_compare, setup};
|
||||
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn array() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[1, 2]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[1: ]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[:-2]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{"id": 0, "name": "Millicent Norman"}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$..friends[2].name",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["Gray Berry", "Gray Berry"]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$..friends[*].name",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
"Vincent Cannon",
|
||||
"Gray Berry",
|
||||
"Millicent Norman",
|
||||
"Vincent Cannon",
|
||||
"Gray Berry"
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$['school']['friends'][*].['name']",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$['school']['friends'][0].['name']",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["Millicent Norman"]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.["eyeColor", "name"]"#,
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!(["blue", "Leonor Herman"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_type() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(@.friends[0])]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(@.friends[10])]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(1==1)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[?(1==1)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([[
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_default() {
|
||||
setup();
|
||||
|
||||
// select_and_then_compare(
|
||||
// "$.school[?(@.friends == @.friends)]",
|
||||
// read_json("./benchmark/data_obj.json"),
|
||||
// json!([{
|
||||
// "friends": [
|
||||
// {"id": 0, "name": "Millicent Norman"},
|
||||
// {"id": 1, "name": "Vincent Cannon" },
|
||||
// {"id": 2, "name": "Gray Berry"}
|
||||
// ]
|
||||
// }]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$.friends[?(@.name)]",
|
||||
// read_json("./benchmark/data_obj.json"),
|
||||
// json!([
|
||||
// { "id" : 1, "name" : "Vincent Cannon" },
|
||||
// { "id" : 2, "name" : "Gray Berry" }
|
||||
// ]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$.friends[?(@.id >= 2)]",
|
||||
// read_json("./benchmark/data_obj.json"),
|
||||
// json!([
|
||||
// { "id" : 2, "name" : "Gray Berry" }
|
||||
// ]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$.friends[?(@.id >= 2 || @.id == 1)]",
|
||||
// read_json("./benchmark/data_obj.json"),
|
||||
// json!([
|
||||
// { "id" : 2, "name" : "Gray Berry" },
|
||||
// { "id" : 1, "name" : "Vincent Cannon" }
|
||||
// ]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]",
|
||||
// read_json("./benchmark/data_obj.json"),
|
||||
// json!([Value::Null]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$..friends[?(@.id == $.index)].id",
|
||||
// read_json("./benchmark/data_obj.json"),
|
||||
// json!([0, 0]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$..book[?($.store.bicycle.price < @.price)].price",
|
||||
// read_json("./benchmark/example.json"),
|
||||
// json!([22.99]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price",
|
||||
// read_json("./benchmark/example.json"),
|
||||
// json!([12.99]),
|
||||
// );
|
||||
//
|
||||
// select_and_then_compare(
|
||||
// "$..[?(@.age > 40)]",
|
||||
// json!([
|
||||
// { "name": "이름1", "age": 40, "phone": "+33 12341234" },
|
||||
// { "name": "이름2", "age": 42, "phone": "++44 12341234" }
|
||||
// ]),
|
||||
// json!([
|
||||
// { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" }
|
||||
// ]),
|
||||
// );
|
||||
|
||||
select_and_then_compare(
|
||||
"$..[?(@.age >= 30)]",
|
||||
json!({
|
||||
"school": {
|
||||
"friends": [
|
||||
{"name": "친구1", "age": 20},
|
||||
{"name": "친구2", "age": 20}
|
||||
]
|
||||
},
|
||||
"friends": [
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구4"}
|
||||
]}),
|
||||
json!([
|
||||
{ "name" : "친구3", "age" : 30 }
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_string() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a == "b")]"#,
|
||||
json!({ "a": "b" }),
|
||||
json!([{ "a": "b" }]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a != "c")]"#,
|
||||
json!({ "a": "b" }),
|
||||
json!([{ "a": "b" }]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a < "b")]"#,
|
||||
json!({ "a": "b" }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a <= "b")]"#,
|
||||
json!({ "a": "b" }),
|
||||
json!([{ "a": "b" }]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a > "b")]"#,
|
||||
json!({ "a": "b" }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a >= "b")]"#,
|
||||
json!({ "a": "b" }),
|
||||
json!([{ "a": "b" }]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_object() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a == @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a != @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a < @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a <= @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a > @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a >= @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_complex() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(1 == @.a)]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?("1" != @.a)]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a <= 1)]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a > "1")]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_compare() {
|
||||
setup();
|
||||
|
||||
for path in [
|
||||
r#"$[?("1" == 1)]"#,
|
||||
r#"$[?(1 == "1")]"#,
|
||||
r#"$[?(true == 1)]"#,
|
||||
r#"$[?(@ == 1)]"#,
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
select_and_then_compare(path, json!({}), json!([Value::Null]));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store.book[*].author"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
"Nigel Rees",
|
||||
"Evelyn Waugh",
|
||||
"Herman Melville",
|
||||
"J. R. R. Tolkien"
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..author"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
"Nigel Rees",
|
||||
"Evelyn Waugh",
|
||||
"Herman Melville",
|
||||
"J. R. R. Tolkien"
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store.*"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
[
|
||||
{"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},
|
||||
{"category" : "fiction", "author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99},
|
||||
{"category" : "fiction", "author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99}
|
||||
],
|
||||
{"color" : "red","price" : 19.95},
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store..price"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([8.95, 12.99, 8.99, 22.99, 19.95]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[2]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[-2]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[0, 1]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"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
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[:2]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"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
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[2:]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
},
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "J. R. R. Tolkien",
|
||||
"title" : "The Lord of the Rings",
|
||||
"isbn" : "0-395-19395-8",
|
||||
"price" : 22.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[?(@.isbn)]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
},
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "J. R. R. Tolkien",
|
||||
"title" : "The Lord of the Rings",
|
||||
"isbn" : "0-395-19395-8",
|
||||
"price" : 22.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store.book[?(@.price < 10)]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "reference",
|
||||
"author" : "Nigel Rees",
|
||||
"title" : "Sayings of the Century",
|
||||
"price" : 8.95
|
||||
},
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..*"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
read_json("./benchmark/giveme_every_thing_result.json"),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filer_same_obj() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..[?(@.a == 1)]"#,
|
||||
json!({
|
||||
"a": 1,
|
||||
"b" : {"a": 1},
|
||||
"c" : {"a": 1}
|
||||
}),
|
||||
json!([
|
||||
{"a": 1},
|
||||
{"a": 1}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[ : ]",
|
||||
json!(["first", "second"]),
|
||||
json!(["first", "second"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[::]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[::2]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "third", "fifth"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[1::]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["second", "third", "forth", "fifth"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[1:2:]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["second"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[1::2]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["second", "forth"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[0:3:1]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "second", "third"]),
|
||||
);
|
||||
select_and_then_compare(
|
||||
"$[0:3:2]",
|
||||
json!(["first", "second", "third", "forth", "fifth"]),
|
||||
json!(["first", "third"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quote() {
|
||||
setup();
|
||||
@@ -621,7 +22,7 @@ fn quote() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_filter() {
|
||||
fn filter_next_all() {
|
||||
setup();
|
||||
|
||||
for path in &[r#"$.*"#, r#"$[*]"#] {
|
||||
@@ -631,6 +32,11 @@ fn all_filter() {
|
||||
json!(["string", 42, { "key": "value" }, [0, 1]]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_all() {
|
||||
setup();
|
||||
|
||||
for path in &[r#"$..*"#, r#"$..[*]"#] {
|
||||
select_and_then_compare(
|
||||
@@ -639,6 +45,11 @@ fn all_filter() {
|
||||
json!([ "string", 42, { "key" : "value" }, [ 0, 1 ], "value", 0, 1 ]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_array_next_all() {
|
||||
setup();
|
||||
|
||||
for path in &[r#"$.*.*"#, r#"$[*].*"#, r#"$.*[*]"#, r#"$[*][*]"#] {
|
||||
select_and_then_compare(
|
||||
@@ -647,6 +58,11 @@ fn all_filter() {
|
||||
json!(["value", 0, 1]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_all_complex() {
|
||||
setup();
|
||||
|
||||
for path in &[r#"$..friends.*"#, r#"$[*].friends.*"#] {
|
||||
select_and_then_compare(
|
||||
@@ -665,8 +81,9 @@ fn all_filter() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn current_path() {
|
||||
fn filter_parent_with_matched_child() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.a[?(@.b.c == 1)]",
|
||||
json!({
|
||||
@@ -684,6 +101,11 @@ fn current_path() {
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_parent_exist_child() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.a[?(@.b.c)]",
|
||||
@@ -705,7 +127,23 @@ fn current_path() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bugs33() {
|
||||
fn filter_parent_paths() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$[?(@.key.subKey == 'subKey2')]",
|
||||
json!([
|
||||
{"key": {"seq": 1, "subKey": "subKey1"}},
|
||||
{"key": {"seq": 2, "subKey": "subKey2"}},
|
||||
{"key": 42},
|
||||
{"some": "value"}
|
||||
]),
|
||||
json!([{"key": {"seq": 2, "subKey": "subKey2"}}]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bugs33_exist_in_all() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
@@ -728,6 +166,11 @@ fn bugs33() {
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bugs33_exist_left_in_all_with_and_condition() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..[?(@.first && @.first.second)]",
|
||||
@@ -749,6 +192,11 @@ fn bugs33() {
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bugs33_exist_right_in_all_with_and_condition() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..[?(@.b.c.d && @.b)]",
|
||||
|
242
tests/jsonpath_examples.rs
Normal file
242
tests/jsonpath_examples.rs
Normal file
@@ -0,0 +1,242 @@
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use common::{read_json, select_and_then_compare, setup};
|
||||
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn example_authros_of_all_books() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store.book[*].author"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
"Nigel Rees",
|
||||
"Evelyn Waugh",
|
||||
"Herman Melville",
|
||||
"J. R. R. Tolkien"
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_authors() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..author"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
"Nigel Rees",
|
||||
"Evelyn Waugh",
|
||||
"Herman Melville",
|
||||
"J. R. R. Tolkien"
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_things_both_books_and_bicycles() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store.*"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
[
|
||||
{"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},
|
||||
{"category" : "fiction", "author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99},
|
||||
{"category" : "fiction", "author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99}
|
||||
],
|
||||
{"color" : "red","price" : 19.95},
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_price_of_everything() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store..price"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([8.95, 12.99, 8.99, 22.99, 19.95]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_third_book() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[2]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_second_to_last_book() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[-2]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_first_two_books() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[0, 1]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"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
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_books_from_index_0_inclusive_until_index_2_exclusive() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[:2]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"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
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_books_from_index_1_inclusive_until_index_2_exclusive() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[2:]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
},
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "J. R. R. Tolkien",
|
||||
"title" : "The Lord of the Rings",
|
||||
"isbn" : "0-395-19395-8",
|
||||
"price" : 22.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_books_with_an_isbn_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..book[?(@.isbn)]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
},
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "J. R. R. Tolkien",
|
||||
"title" : "The Lord of the Rings",
|
||||
"isbn" : "0-395-19395-8",
|
||||
"price" : 22.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_books_in_store_cheaper_than_10() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.store.book[?(@.price < 10)]"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([
|
||||
{
|
||||
"category" : "reference",
|
||||
"author" : "Nigel Rees",
|
||||
"title" : "Sayings of the Century",
|
||||
"price" : 8.95
|
||||
},
|
||||
{
|
||||
"category" : "fiction",
|
||||
"author" : "Herman Melville",
|
||||
"title" : "Moby Dick",
|
||||
"isbn" : "0-553-21311-3",
|
||||
"price" : 8.99
|
||||
}
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn give_me_every_thing() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..*"#,
|
||||
read_json("./benchmark/example.json"),
|
||||
read_json("./benchmark/giveme_every_thing_result.json"),
|
||||
);
|
||||
}
|
378
tests/op.rs
Normal file
378
tests/op.rs
Normal file
@@ -0,0 +1,378 @@
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
use common::{read_json, select_and_then_compare, setup};
|
||||
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn op_object_eq() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(@.friends == @.friends)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_object_ge() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.friends[?(@.id >= 2)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{ "id" : 2, "name" : "Gray Berry" }
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_object_or_default() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.friends[?(@.id >= 2 || @.id == 1)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{ "id" : 2, "name" : "Gray Berry" },
|
||||
{ "id" : 1, "name" : "Vincent Cannon" }
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_object_and_or() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_result_type() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..friends[?(@.id == $.index)].id",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([0, 0]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_absolute_path_result_type() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..book[?($.store.bicycle.price < @.price)].price",
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([22.99]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_complicated() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price",
|
||||
read_json("./benchmark/example.json"),
|
||||
json!([12.99]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_gt() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..[?(@.age > 40)]",
|
||||
json!([
|
||||
{ "name": "이름1", "age": 40, "phone": "+33 12341234" },
|
||||
{ "name": "이름2", "age": 42, "phone": "++44 12341234" }
|
||||
]),
|
||||
json!([
|
||||
{ "name" : "이름2", "age" : 42, "phone" : "++44 12341234" }
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ge() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$..[?(@.age >= 30)]",
|
||||
json!({
|
||||
"school": {
|
||||
"friends": [
|
||||
{"name": "친구1", "age": 20},
|
||||
{"name": "친구2", "age": 20}
|
||||
]
|
||||
},
|
||||
"friends": [
|
||||
{"name": "친구3", "age": 30},
|
||||
{"name": "친구4"}
|
||||
]}),
|
||||
json!([
|
||||
{ "name" : "친구3", "age" : 30 }
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_eq_for_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ne_for_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_lt_for_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_le_for_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_gt_for_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ge_for_number() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn op_eq_for_string_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a == "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ne_for_string_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a != "c")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_lt_for_string_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a < "b")]"#, json!({ "a": "b" }), json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_le_for_string_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a <= "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_gt_for_string_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a > "b")]"#, json!({ "a": "b" }), json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ge_for_string_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a >= "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_eq_for_object_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a == @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ne_for_object_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a != @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_lt_for_object_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a < @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_le_for_object_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a <= @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_gt_for_object_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a > @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ge_for_object_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a >= @.c)]"#,
|
||||
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_eq_for_complex_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(1 == @.a)]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_ne_for_complex_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?("1" != @.a)]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_le_for_complex_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a <= 1)]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_gt_for_complex_value() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$.[?(@.a > "1")]"#,
|
||||
json!({ "a": { "b": 1 } }),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_compare_different_types() {
|
||||
setup();
|
||||
|
||||
for path in [
|
||||
r#"$[?("1" == 1)]"#,
|
||||
r#"$[?(1 == "1")]"#,
|
||||
r#"$[?(true == 1)]"#,
|
||||
r#"$[?(@ == 1)]"#,
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
select_and_then_compare(path, json!({}), json!([Value::Null]));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn op_for_same_type() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
r#"$..[?(@.a == 1)]"#,
|
||||
json!({
|
||||
"a": 1,
|
||||
"b" : {"a": 1},
|
||||
"c" : {"a": 1}
|
||||
}),
|
||||
json!([
|
||||
{"a": 1},
|
||||
{"a": 1}
|
||||
]),
|
||||
);
|
||||
}
|
99
tests/return_type.rs
Normal file
99
tests/return_type.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
use common::{read_json, select_and_then_compare, setup};
|
||||
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn return_type_for_single_object() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_type_for_single_object_key_matched() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.friends[?(@.name)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([
|
||||
{ "id" : 1, "name" : "Vincent Cannon" },
|
||||
{ "id" : 2, "name" : "Gray Berry" }
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_type_for_child_object_matched() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(@.friends[0])]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_type_for_child_object_not_matched() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(@.friends[10])]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([Value::Null]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_type_for_object_filter_true() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school[?(1==1)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([{
|
||||
"friends": [
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]
|
||||
}]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_type_for_array_filter_true() {
|
||||
setup();
|
||||
|
||||
select_and_then_compare(
|
||||
"$.school.friends[?(1==1)]",
|
||||
read_json("./benchmark/data_obj.json"),
|
||||
json!([[
|
||||
{"id": 0, "name": "Millicent Norman"},
|
||||
{"id": 1, "name": "Vincent Cannon" },
|
||||
{"id": 2, "name": "Gray Berry"}
|
||||
]]),
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user