Skip to content

Commit 0fad7cb

Browse files
committed
Add string type coercions for primitive values
1 parent 3751908 commit 0fad7cb

4 files changed

Lines changed: 81 additions & 3 deletions

File tree

src/json_get_bool.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ fn jiter_json_get_bool(json_data: Option<&str>, path: &[JsonPath]) -> Result<boo
7979
if let Some((mut jiter, peek)) = jiter_json_find(json_data, path) {
8080
match peek {
8181
Peek::True | Peek::False => Ok(jiter.known_bool(peek)?),
82+
Peek::String => {
83+
let s = jiter.known_str()?;
84+
s.parse::<bool>().map_err(|_| GetError)
85+
}
8286
_ => get_err!(),
8387
}
8488
} else {

src/json_get_float.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,17 @@ impl InvokeResult for Float64Array {
104104
fn jiter_json_get_float(json_data: Option<&str>, path: &[JsonPath]) -> Result<f64, GetError> {
105105
if let Some((mut jiter, peek)) = jiter_json_find(json_data, path) {
106106
match peek {
107+
Peek::String => {
108+
let s = jiter.known_str()?;
109+
s.parse::<f64>().map_err(|_| GetError)
110+
}
107111
// numbers are represented by everything else in peek, hence doing it this way
108112
Peek::Null
109113
| Peek::True
110114
| Peek::False
111115
| Peek::Minus
112116
| Peek::Infinity
113117
| Peek::NaN
114-
| Peek::String
115118
| Peek::Array
116119
| Peek::Object => get_err!(),
117120
_ => match jiter.known_number(peek)? {

src/json_get_int.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,16 @@ impl InvokeResult for Int64Array {
104104
fn jiter_json_get_int(json_data: Option<&str>, path: &[JsonPath]) -> Result<i64, GetError> {
105105
if let Some((mut jiter, peek)) = jiter_json_find(json_data, path) {
106106
match peek {
107-
// numbers are represented by everything else in peek, hence doing it this way
107+
Peek::String => {
108+
let s = jiter.known_str()?;
109+
s.parse::<i64>().map_err(|_| GetError)
110+
}
108111
Peek::Null
109112
| Peek::True
110113
| Peek::False
111114
| Peek::Minus
112115
| Peek::Infinity
113116
| Peek::NaN
114-
| Peek::String
115117
| Peek::Array
116118
| Peek::Object => get_err!(),
117119
_ => match jiter.known_int(peek)? {

tests/main.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,75 @@ async fn test_json_get_int() {
284284
assert_eq!(display_val(batches).await, (DataType::Int64, "2".to_string()));
285285
}
286286

287+
#[tokio::test]
288+
async fn test_json_get_int_string_parse() {
289+
// string containing int
290+
let batches = run_query(r#"select json_get_int('{"foo": "123"}', 'foo')"#)
291+
.await
292+
.unwrap();
293+
assert_eq!(display_val(batches).await, (DataType::Int64, "123".to_string()));
294+
295+
// negative string
296+
let batches = run_query(r#"select json_get_int('{"foo": "-42"}', 'foo')"#)
297+
.await
298+
.unwrap();
299+
assert_eq!(display_val(batches).await, (DataType::Int64, "-42".to_string()));
300+
301+
// non-numeric string returns null
302+
let batches = run_query(r#"select json_get_int('{"foo": "abc"}', 'foo')"#)
303+
.await
304+
.unwrap();
305+
assert_eq!(display_val(batches).await, (DataType::Int64, String::new()));
306+
307+
// float string returns null (not a valid int)
308+
let batches = run_query(r#"select json_get_int('{"foo": "1.5"}', 'foo')"#)
309+
.await
310+
.unwrap();
311+
assert_eq!(display_val(batches).await, (DataType::Int64, String::new()));
312+
}
313+
314+
#[tokio::test]
315+
async fn test_json_get_float_string_parse() {
316+
// string containing float
317+
let batches = run_query(r#"select json_get_float('{"foo": "1.5"}', 'foo')"#)
318+
.await
319+
.unwrap();
320+
assert_eq!(display_val(batches).await, (DataType::Float64, "1.5".to_string()));
321+
322+
// string containing int parses as float
323+
let batches = run_query(r#"select json_get_float('{"foo": "42"}', 'foo')"#)
324+
.await
325+
.unwrap();
326+
assert_eq!(display_val(batches).await, (DataType::Float64, "42.0".to_string()));
327+
328+
// non-numeric string returns null
329+
let batches = run_query(r#"select json_get_float('{"foo": "abc"}', 'foo')"#)
330+
.await
331+
.unwrap();
332+
assert_eq!(display_val(batches).await, (DataType::Float64, String::new()));
333+
}
334+
335+
#[tokio::test]
336+
async fn test_json_get_bool_string_parse() {
337+
// string "true"
338+
let batches = run_query(r#"select json_get_bool('{"foo": "true"}', 'foo')"#)
339+
.await
340+
.unwrap();
341+
assert_eq!(display_val(batches).await, (DataType::Boolean, "true".to_string()));
342+
343+
// string "false"
344+
let batches = run_query(r#"select json_get_bool('{"foo": "false"}', 'foo')"#)
345+
.await
346+
.unwrap();
347+
assert_eq!(display_val(batches).await, (DataType::Boolean, "false".to_string()));
348+
349+
// non-bool string returns null
350+
let batches = run_query(r#"select json_get_bool('{"foo": "abc"}', 'foo')"#)
351+
.await
352+
.unwrap();
353+
assert_eq!(display_val(batches).await, (DataType::Boolean, String::new()));
354+
}
355+
287356
#[tokio::test]
288357
async fn test_json_get_path() {
289358
let batches = run_query(r#"select json_get('{"i": 19}', 'i')::int<20"#).await.unwrap();

0 commit comments

Comments
 (0)