From bd7f7982a149b5f99eb21bf1800616679095fcf9 Mon Sep 17 00:00:00 2001 From: Dadepo Aderemi Date: Sat, 18 Nov 2023 18:45:33 +0400 Subject: [PATCH] added test for json when json is invalid --- df_extras_sqlite/src/json_udfs.rs | 42 ++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/df_extras_sqlite/src/json_udfs.rs b/df_extras_sqlite/src/json_udfs.rs index 17376b9..78a388e 100644 --- a/df_extras_sqlite/src/json_udfs.rs +++ b/df_extras_sqlite/src/json_udfs.rs @@ -5,17 +5,20 @@ use datafusion::common::DataFusionError; use datafusion::error::Result; use serde_json::Value; +/// The json(X) function verifies that its argument X is a valid JSON string and returns a minified +/// version of that JSON string (with all unnecessary whitespace removed). +/// If X is not a well-formed JSON string, then this routine throws an error. pub fn json(args: &[ArrayRef]) -> Result { let json_strings = datafusion::common::cast::as_string_array(&args[0])?; let mut string_builder = StringBuilder::with_capacity(json_strings.len(), u8::MAX as usize); json_strings.iter().try_for_each(|json_string| { if let Some(json_string) = json_string { - let value: Value = serde_json::from_str(json_string).map_err(|e| { - DataFusionError::Internal(format!("Parsing {json_string} failed with error {e}")) + let value: Value = serde_json::from_str(json_string).map_err(|_| { + DataFusionError::Internal("Runtime error: malformed JSON".to_string()) })?; - let pretty_json = serde_json::to_string(&value).map_err(|e| { - DataFusionError::Internal(format!("Parsing {json_string} failed with error {e}")) + let pretty_json = serde_json::to_string(&value).map_err(|_| { + DataFusionError::Internal("Runtime error: malformed JSON".to_string()) })?; string_builder.append_value(pretty_json); Ok::<(), DataFusionError>(()) @@ -28,6 +31,15 @@ pub fn json(args: &[ArrayRef]) -> Result { Ok(Arc::new(string_builder.finish()) as ArrayRef) } +/// The json_valid(X) function return 1 if the argument X is well-formed canonical RFC-7159 JSON +/// without any extensions, or return 0 if the argument X is not well-formed JSON or is +/// JSON that includes JSON5 extensions. +/// +/// Examples: +/// +/// json_valid('{"x":35}') → 1 +/// json_valid('{"x":35') → 0 +/// json_valid(NULL) → NULL pub fn json_valid(args: &[ArrayRef]) -> Result { let json_strings = datafusion::common::cast::as_string_array(&args[0])?; let mut uint_builder = UInt8Array::builder(json_strings.len()); @@ -87,6 +99,28 @@ mod tests { Ok(()) } + #[tokio::test] + async fn test_invalid_json() -> Result<()> { + let ctx = register_udfs_for_test()?; + let df = ctx + .sql( + r#"select index, json(' { "this" : "is", "a": [ "test" ] ') as col_result FROM json_table ORDER BY index ASC"#, + ) + .await?; + + let result = df.clone().collect().await; + + assert!(&result + .err() + .unwrap() + .find_root() + .find_root() + .to_string() + .contains("Internal error: Runtime error: malformed JSON")); + + Ok(()) + } + #[tokio::test] async fn test_json_valid() -> Result<()> { let ctx = register_udfs_for_test()?;