Skip to content

Commit 7c5a58e

Browse files
fix(json): handle text-based JSON in json() blob arguments
1 parent 46740ee commit 7c5a58e

File tree

3 files changed

+147
-4
lines changed

3 files changed

+147
-4
lines changed

core/json/mod.rs

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,15 @@ pub fn get_json(json_value: &Value, indent: Option<&str>) -> crate::Result<Value
4949

5050
Ok(Value::Text(Text::json(json)))
5151
}
52-
Value::Blob(b) => {
53-
let jsonbin = Jsonb::new(b.len(), Some(b));
54-
jsonbin.element_type()?;
55-
Ok(Value::Text(Text::json(jsonbin.to_string())))
52+
Value::Blob(_) => {
53+
// Blobs can contain either text JSON or binary JSONB
54+
// Use convert_dbtype_to_jsonb to properly detect and parse both formats
55+
let json_val = convert_dbtype_to_jsonb(json_value, Conv::Strict)?;
56+
let json = match indent {
57+
Some(indent) => json_val.to_string_pretty(Some(indent))?,
58+
None => json_val.to_string(),
59+
};
60+
Ok(Value::Text(Text::json(json)))
5661
}
5762
Value::Null => Ok(Value::Null),
5863
_ => {
@@ -905,6 +910,54 @@ mod tests {
905910
}
906911
}
907912

913+
#[test]
914+
fn test_get_json_blob_text_json() {
915+
let true_blob = Value::Blob(b"true".to_vec());
916+
let result = get_json(&true_blob, None).unwrap();
917+
if let Value::Text(result_str) = result {
918+
assert_eq!(result_str.as_str(), "true");
919+
assert_eq!(result_str.subtype, TextSubtype::Json);
920+
} else {
921+
panic!("Expected Value::Text, got: {:?}", result);
922+
}
923+
924+
let false_blob = Value::Blob(b"false".to_vec());
925+
let result = get_json(&false_blob, None).unwrap();
926+
if let Value::Text(result_str) = result {
927+
assert_eq!(result_str.as_str(), "false");
928+
assert_eq!(result_str.subtype, TextSubtype::Json);
929+
} else {
930+
panic!("Expected Value::Text, got: {:?}", result);
931+
}
932+
933+
let null_blob = Value::Blob(b"null".to_vec());
934+
let result = get_json(&null_blob, None).unwrap();
935+
if let Value::Text(result_str) = result {
936+
assert_eq!(result_str.as_str(), "null");
937+
assert_eq!(result_str.subtype, TextSubtype::Json);
938+
} else {
939+
panic!("Expected Value::Text, got: {:?}", result);
940+
}
941+
942+
let number_blob = Value::Blob(b"123".to_vec());
943+
let result = get_json(&number_blob, None).unwrap();
944+
if let Value::Text(result_str) = result {
945+
assert_eq!(result_str.as_str(), "123");
946+
assert_eq!(result_str.subtype, TextSubtype::Json);
947+
} else {
948+
panic!("Expected Value::Text, got: {:?}", result);
949+
}
950+
951+
let string_blob = Value::Blob(b"\"hello\"".to_vec());
952+
let result = get_json(&string_blob, None).unwrap();
953+
if let Value::Text(result_str) = result {
954+
assert_eq!(result_str.as_str(), "\"hello\"");
955+
assert_eq!(result_str.subtype, TextSubtype::Json);
956+
} else {
957+
panic!("Expected Value::Text, got: {:?}", result);
958+
}
959+
}
960+
908961
#[test]
909962
fn test_get_json_non_text() {
910963
let input = Value::Null;
@@ -958,6 +1011,36 @@ mod tests {
9581011
}
9591012
}
9601013

1014+
#[test]
1015+
fn test_json_object_blob_invalid() {
1016+
let key = Value::build_text("a");
1017+
let blob = Value::Blob("true".as_bytes().to_vec());
1018+
1019+
let input = [key, blob];
1020+
1021+
let result = json_object(&input);
1022+
1023+
match result {
1024+
Ok(_) => panic!("Expected error for blob value in json_object"),
1025+
Err(e) => assert!(e.to_string().contains("JSON cannot hold BLOB values")),
1026+
}
1027+
}
1028+
1029+
#[test]
1030+
fn test_json_set_blob_invalid() {
1031+
let json_cache = JsonCacheCell::new();
1032+
let blob = Value::Blob("test".as_bytes().to_vec());
1033+
let result = json_set(
1034+
&[Value::build_text("{}"), Value::build_text("$.field"), blob],
1035+
&json_cache,
1036+
);
1037+
1038+
match result {
1039+
Ok(_) => panic!("Expected error for blob value in json_set"),
1040+
Err(e) => assert!(e.to_string().contains("JSON cannot hold BLOB values")),
1041+
}
1042+
}
1043+
9611044
#[test]
9621045
fn test_json_array_length() {
9631046
let input = Value::build_text("[1,2,3,4]");

core/json/ops.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,38 @@ mod tests {
462462
assert!(json_remove(&args, &json_cache).is_err());
463463
}
464464

465+
#[test]
466+
fn test_json_insert_blob_invalid() {
467+
let json_cache = JsonCacheCell::new();
468+
let blob = Value::Blob("test".as_bytes().to_vec());
469+
let args = [create_json("{}"), create_text("$.field"), blob];
470+
471+
let result = json_insert(&args, &json_cache);
472+
473+
match result {
474+
Ok(_) => panic!("Expected error for blob value in json_insert"),
475+
Err(e) => assert!(e.to_string().contains("JSON cannot hold BLOB values")),
476+
}
477+
}
478+
479+
#[test]
480+
fn test_json_replace_blob_invalid() {
481+
let json_cache = JsonCacheCell::new();
482+
let blob = Value::Blob("test".as_bytes().to_vec());
483+
let args = [
484+
create_json(r#"{"field":"value"}"#),
485+
create_text("$.field"),
486+
blob,
487+
];
488+
489+
let result = json_replace(&args, &json_cache);
490+
491+
match result {
492+
Ok(_) => panic!("Expected error for blob value in json_replace"),
493+
Err(e) => assert!(e.to_string().contains("JSON cannot hold BLOB values")),
494+
}
495+
}
496+
465497
#[test]
466498
fn test_json_remove_complex_case() {
467499
let args = [

testing/json.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,34 @@ do_execsql_test json5-multi-comment-pretty {
148148
"aaa": 123
149149
}}}
150150

151+
do_execsql_test json-blob-text-true {
152+
SELECT json(x'74727565');
153+
} {true}
154+
155+
do_execsql_test json-blob-text-false {
156+
SELECT json(x'66616c7365');
157+
} {false}
158+
159+
do_execsql_test json-blob-text-null {
160+
SELECT json(x'6e756c6c');
161+
} {null}
162+
163+
do_execsql_test json-blob-text-number {
164+
SELECT json(x'313233');
165+
} {123}
166+
167+
do_execsql_test json-blob-text-string {
168+
SELECT json(x'2268656c6c6f22');
169+
} {{"hello"}}
170+
171+
do_execsql_test json-blob-text-array {
172+
SELECT json(x'5b312c322c335d');
173+
} {{[1,2,3]}}
174+
175+
do_execsql_test json-blob-text-object {
176+
SELECT json(x'7b226b6579223a2276616c7565227d');
177+
} {{{"key":"value"}}}
178+
151179
do_execsql_test json-pretty-ident-1 {
152180
SELECT json_pretty('{x: 1}', '');
153181
} {{{

0 commit comments

Comments
 (0)