diff --git a/src/json_get_bool.rs b/src/json_get_bool.rs index 2a24420..57d04c4 100644 --- a/src/json_get_bool.rs +++ b/src/json_get_bool.rs @@ -79,6 +79,10 @@ fn jiter_json_get_bool(json_data: Option<&str>, path: &[JsonPath]) -> Result Ok(jiter.known_bool(peek)?), + Peek::String => { + let s = jiter.known_str()?; + s.parse::().map_err(|_| GetError) + } _ => get_err!(), } } else { diff --git a/src/json_get_float.rs b/src/json_get_float.rs index 05feabb..968b72e 100644 --- a/src/json_get_float.rs +++ b/src/json_get_float.rs @@ -104,6 +104,10 @@ impl InvokeResult for Float64Array { fn jiter_json_get_float(json_data: Option<&str>, path: &[JsonPath]) -> Result { if let Some((mut jiter, peek)) = jiter_json_find(json_data, path) { match peek { + Peek::String => { + let s = jiter.known_str()?; + s.parse::().map_err(|_| GetError) + } // numbers are represented by everything else in peek, hence doing it this way Peek::Null | Peek::True @@ -111,7 +115,6 @@ fn jiter_json_get_float(json_data: Option<&str>, path: &[JsonPath]) -> Result get_err!(), _ => match jiter.known_number(peek)? { diff --git a/src/json_get_int.rs b/src/json_get_int.rs index 1fa2b04..d4bc791 100644 --- a/src/json_get_int.rs +++ b/src/json_get_int.rs @@ -104,14 +104,16 @@ impl InvokeResult for Int64Array { fn jiter_json_get_int(json_data: Option<&str>, path: &[JsonPath]) -> Result { if let Some((mut jiter, peek)) = jiter_json_find(json_data, path) { match peek { - // numbers are represented by everything else in peek, hence doing it this way + Peek::String => { + let s = jiter.known_str()?; + s.parse::().map_err(|_| GetError) + } Peek::Null | Peek::True | Peek::False | Peek::Minus | Peek::Infinity | Peek::NaN - | Peek::String | Peek::Array | Peek::Object => get_err!(), _ => match jiter.known_int(peek)? { diff --git a/tests/main.rs b/tests/main.rs index cbc371c..003b29c 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -284,6 +284,75 @@ async fn test_json_get_int() { assert_eq!(display_val(batches).await, (DataType::Int64, "2".to_string())); } +#[tokio::test] +async fn test_json_get_int_string_parse() { + // string containing int + let batches = run_query(r#"select json_get_int('{"foo": "123"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Int64, "123".to_string())); + + // negative string + let batches = run_query(r#"select json_get_int('{"foo": "-42"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Int64, "-42".to_string())); + + // non-numeric string returns null + let batches = run_query(r#"select json_get_int('{"foo": "abc"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Int64, String::new())); + + // float string returns null (not a valid int) + let batches = run_query(r#"select json_get_int('{"foo": "1.5"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Int64, String::new())); +} + +#[tokio::test] +async fn test_json_get_float_string_parse() { + // string containing float + let batches = run_query(r#"select json_get_float('{"foo": "1.5"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Float64, "1.5".to_string())); + + // string containing int parses as float + let batches = run_query(r#"select json_get_float('{"foo": "42"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Float64, "42.0".to_string())); + + // non-numeric string returns null + let batches = run_query(r#"select json_get_float('{"foo": "abc"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Float64, String::new())); +} + +#[tokio::test] +async fn test_json_get_bool_string_parse() { + // string "true" + let batches = run_query(r#"select json_get_bool('{"foo": "true"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Boolean, "true".to_string())); + + // string "false" + let batches = run_query(r#"select json_get_bool('{"foo": "false"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Boolean, "false".to_string())); + + // non-bool string returns null + let batches = run_query(r#"select json_get_bool('{"foo": "abc"}', 'foo')"#) + .await + .unwrap(); + assert_eq!(display_val(batches).await, (DataType::Boolean, String::new())); +} + #[tokio::test] async fn test_json_get_path() { let batches = run_query(r#"select json_get('{"i": 19}', 'i')::int<20"#).await.unwrap();