Skip to main content

Crate specta_serde

Crate specta_serde 

Source
Expand description

Serde support for Specta.

§Choosing a mode

  • Use Format when serde behavior is symmetric and a single exported shape should work for both serialization and deserialization.
  • Use PhasesFormat when serde behavior differs by direction (for example deserialize-widening enums, asymmetric conversion attributes, or explicit Phased overrides).

§serde_with and #[serde(with = ...)]

serde_with is supported through the same mechanism as raw serde codec attributes because it expands to serde metadata (with, serialize_with, deserialize_with).

When codecs change the wire type, add an explicit Specta override:

use serde::{Deserialize, Serialize};
use specta::Type;

#[derive(Type, Serialize, Deserialize)]
struct Digest {
    #[serde(with = "hex_bytes")]
    #[specta(type = String)]
    value: Vec<u8>,
}

If serialize and deserialize shapes are different, use Phased and PhasesFormat.

This is required because a single unified type graph cannot represent two different directional wire shapes at once.

use serde::{Deserialize, Serialize};
use serde_with::{OneOrMany, serde_as};
use specta::{Type, Types};

#[derive(Type, Serialize, Deserialize)]
#[serde(untagged)]
enum OneOrManyString {
    One(String),
    Many(Vec<String>),
}

#[serde_as]
#[derive(Type, Serialize, Deserialize)]
struct Filters {
    #[serde_as(as = "OneOrMany<_>")]
    #[specta(type = specta_serde::Phased<Vec<String>, OneOrManyString>)]
    tags: Vec<String>,
}

let types = Types::default().register::<Filters>();
let phased_types = specta_typescript::Typescript::default()
    .export(&types, specta_serde::PhasesFormat)?;

As an alternative to codec attributes, #[serde(into = ...)], #[serde(from = ...)], and #[serde(try_from = ...)] often produce better type inference because the wire type is modeled as an explicit Rust type:

use serde::{Deserialize, Serialize};
use specta::Type;

#[derive(Type, Serialize, Deserialize)]
struct UserWire {
    id: String,
}

#[derive(Type, Clone, Serialize, Deserialize)]
#[serde(into = "UserWire")]
struct UserInto {
    id: String,
}

#[derive(Type, Clone, Serialize, Deserialize)]
#[serde(from = "UserWire")]
struct UserFrom {
    id: String,
}

#[derive(Type, Clone, Serialize, Deserialize)]
#[serde(try_from = "UserWire")]
struct UserTryFrom {
    id: String,
}

See examples/basic-ts/src/main.rs for a complete exporter example using Format and PhasesFormat.

Structs§

Error
Error type for serde transformation and validation failures.
Format
Applies serde-aware rewrites to a single shared type graph.
Phased
Declares an explicit serialize/deserialize type pair for Specta output.
PhasesFormat
Applies serde-aware rewrites while preserving separate serialize and deserialize shapes.

Enums§

Phase
Selects which directional type shape to use with PhasesFormat.

Functions§

phased
Builds an explicit phased DataType from precomputed serialize and deserialize shapes.
select_phase_datatype
Rewrites a DataType to the requested directional shape for PhasesFormat.