serde-sqlx

Crates.ioserde-sqlx
lib.rsserde-sqlx
version0.0.1
sourcesrc
created_at2025-03-19 18:11:30.623435+00
updated_at2025-03-19 18:11:30.623435+00
descriptionAllows deserializing Postgres rows into Rust types using serde
homepage
repositoryhttps://github.com/vrmiguel/serde-sqlx
max_upload_size
id1598433
size49,958
Vinícius Miguel (vrmiguel)

documentation

README

serde-sqlx

Allows deserializing Postgres rows into Rust types using serde. Work in progress.

Implementation Status

Completed ✅

  • Simple Primitives:

    • Strings: TEXT, VARCHAR, BPCHAR
    • Booleans
    • Integers: i16, i32, i64 (INT2, INT4, INT8/BIGINT)
    • Floating point: f32 (REAL), f64 (DOUBLE PRECISION)
    • Support for special float values (NaN, Infinity)
  • Structs and Tuples:

    • Deserialize into named structs with primitive fields
    • Support for tuple structs and anonymous tuples
    • Deep nesting of structs using Serde's flattening
  • Optional Values:

    • NULL values into Option
  • JSON and JSONB:

    • Directly deserialize JSON data into Rust structures
  • Newtypes:

    • Support for newtype pattern (e.g., struct UserId(i32))
  • PostgreSQL Arrays:

    • Convert Postgres arrays into Rust vectors
    • Support for arrays of primitive types and nullable types

Planned/untested 📝

  • Enums:
    • Support for Rust enums with Postgres enums or discriminated JSON
  • Timestamps and Dates:
    • Testing for chrono and time types
  • UUID:
    • Testing for uuid crate types

Usage

Add serde-sqlx to your Cargo.toml:

[dependencies]
serde-sqlx = "0.1"
serde = { version = "1", features = ["derive"] }
sqlx = { version = "0.6", features = ["postgres", "runtime-tokio-native-tls"] }

Basic example:

use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct User {
    id: i32,
    name: String,
    active: bool,
    profile: Option<Profile>,
}

#[derive(Deserialize, Debug)]
struct Profile {
    bio: String,
    age: i32,
}

async fn get_users(pool: &PgPool) -> anyhow::Result<Vec<User>> {
    let rows = sqlx::query(
        "SELECT id, name, active, profile::JSONB FROM users"
    ).fetch_all(pool).await?;

    let users: Result<Vec<_>, _> = rows.into_iter()
        .map(serde_sqlx::from_pg_row)
        .collect();

    users.map_err(Into::into)
}
Commit count: 0

cargo fmt