1- use std:: any:: Any ;
1+ use crate :: common:: { invoke, parse_jsonpath, return_type_check} ;
2+ use crate :: common_macros:: make_udf_function;
3+ use crate :: json_get_json:: jiter_json_get_json;
24use datafusion:: arrow:: array:: StringArray ;
35use datafusion:: arrow:: datatypes:: { DataType , DataType :: Utf8 } ;
46use datafusion:: common:: { exec_err, Result as DataFusionResult , ScalarValue } ;
57use datafusion:: logical_expr:: { ColumnarValue , ScalarFunctionArgs , ScalarUDFImpl , Signature , Volatility } ;
6- use jsonpath_rust:: parser:: model:: { Segment , Selector } ;
7- use jsonpath_rust:: parser:: parse_json_path;
8- use crate :: common:: { invoke, return_type_check, JsonPath } ;
9- use crate :: common_macros:: make_udf_function;
10- use crate :: json_get_json:: jiter_json_get_json;
8+ use std:: any:: Any ;
119
1210make_udf_function ! (
1311 JsonExtract ,
@@ -65,55 +63,20 @@ impl ScalarUDFImpl for JsonExtract {
6563
6664 let path_str = match path_arg {
6765 ColumnarValue :: Scalar ( ScalarValue :: Utf8 ( Some ( s) ) ) => s,
68- _ => return exec_err ! ( "'{}' expects a valid JSONPath string (e.g., '$.key[0]') as second argument" , self . name( ) ) ,
66+ _ => {
67+ return exec_err ! (
68+ "'{}' expects a valid JSONPath string (e.g., '$.key[0]') as second argument" ,
69+ self . name( )
70+ )
71+ }
6972 } ;
7073
7174 let path = parse_jsonpath ( path_str) ;
7275
73- invoke :: < StringArray > ( & [ json_arg. clone ( ) ] , |json, _| {
74- jiter_json_get_json ( json, & path)
75- } )
76+ invoke :: < StringArray > ( & [ json_arg. clone ( ) ] , |json, _| jiter_json_get_json ( json, & path) )
7677 }
7778
7879 fn aliases ( & self ) -> & [ String ] {
7980 & self . aliases
8081 }
8182}
82-
83- fn parse_jsonpath ( path : & str ) -> Vec < JsonPath < ' static > > {
84- let segments = parse_json_path ( path)
85- . map ( |it| it. segments )
86- . unwrap_or ( Vec :: new ( ) ) ;
87-
88- segments. into_iter ( ) . map ( |segment| {
89- match segment {
90- Segment :: Selector ( s) => match s {
91- Selector :: Name ( name) => JsonPath :: Key ( Box :: leak ( name. into_boxed_str ( ) ) ) ,
92- Selector :: Index ( idx) => JsonPath :: Index ( idx as usize ) ,
93- _ => JsonPath :: None ,
94- } ,
95- _ => JsonPath :: None ,
96- }
97- } ) . collect :: < Vec < _ > > ( )
98- }
99-
100- #[ cfg( test) ]
101- mod tests {
102- use rstest:: rstest;
103- use super :: * ;
104-
105- // Test cases for parse_jsonpath
106- #[ rstest]
107- #[ case( "$.a.aa" , vec![ JsonPath :: Key ( "a" ) , JsonPath :: Key ( "aa" ) ] ) ]
108- #[ case( "$.a.ab[0].ac" , vec![ JsonPath :: Key ( "a" ) , JsonPath :: Key ( "ab" ) , JsonPath :: Index ( 0 ) , JsonPath :: Key ( "ac" ) ] ) ]
109- #[ case( "$.a.ab[1].ad" , vec![ JsonPath :: Key ( "a" ) , JsonPath :: Key ( "ab" ) , JsonPath :: Index ( 1 ) , JsonPath :: Key ( "ad" ) ] ) ]
110- #[ case( r#"$.a["a b"].ad"# , vec![ JsonPath :: Key ( "a" ) , JsonPath :: Key ( "\" a b\" " ) , JsonPath :: Key ( "ad" ) ] ) ]
111- #[ tokio:: test]
112- async fn test_parse_jsonpath (
113- #[ case] path : & str ,
114- #[ case] expected : Vec < JsonPath < ' static > > ,
115- ) {
116- let result = parse_jsonpath ( path) ;
117- assert_eq ! ( result, expected) ;
118- }
119- }
0 commit comments