From 3a53ff4beea88c7b48a75e5d97fa90772e87af34 Mon Sep 17 00:00:00 2001 From: Xiangkai Zeng Date: Sat, 20 Jun 2026 06:47:04 +0000 Subject: [PATCH] Add SQLite integration test for #[sqlx(json)] on TEXT columns Covers reading a JSON-as-TEXT column into a FromRow struct field annotated with #[sqlx(json)], and the error path where invalid JSON surfaces as sqlx::Error::ColumnDecode. Co-Authored-By: Claude Opus 4.8 --- tests/sqlite/derives.rs | 52 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/tests/sqlite/derives.rs b/tests/sqlite/derives.rs index 3491ab8539..3fff26fd42 100644 --- a/tests/sqlite/derives.rs +++ b/tests/sqlite/derives.rs @@ -1,5 +1,5 @@ use sqlx::Sqlite; -use sqlx_test::test_type; +use sqlx_test::{new, test_type}; #[derive(Debug, PartialEq, sqlx::Type)] #[repr(u32)] @@ -32,3 +32,53 @@ test_type!(transparent_named(Sqlite, "0" == TransparentNamed { field: 0 }, "23523" == TransparentNamed { field: 23523 }, )); + +// SQLite stores JSON as TEXT. The `#[sqlx(json)]` field attribute lets a struct +// read such a column into a `serde_json::Value` (or any `Deserialize` type), +// deserializing it with `serde_json` during decode. +#[derive(Debug, PartialEq, sqlx::FromRow)] +struct JsonRow { + id: i64, + #[sqlx(json)] + data: serde_json::Value, +} + +#[sqlx_macros::test] +async fn it_reads_json_from_text_column() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let row: JsonRow = sqlx::query_as( + r#"SELECT 1 AS id, '{"key": "value"}' AS data"#, + ) + .fetch_one(&mut conn) + .await?; + + assert_eq!( + row, + JsonRow { + id: 1, + data: serde_json::json!({ "key": "value" }), + } + ); + + Ok(()) +} + +#[sqlx_macros::test] +async fn it_surfaces_invalid_json_as_column_decode_error() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let result: Result = + sqlx::query_as(r#"SELECT 1 AS id, 'not valid json' AS data"#) + .fetch_one(&mut conn) + .await; + + match result { + Err(sqlx::Error::ColumnDecode { index, .. }) => { + assert_eq!(index, "\"data\""); + } + other => panic!("expected ColumnDecode error, got {other:?}"), + } + + Ok(()) +}