Latest: v0.4.1 · on crates.io

Laminate

Data, shaped layer by layer.

lam·i·nate /ˈlaməˌnāt/ verb

To bond layers of material together, each adding strength and structure to the whole. In software: to progressively shape raw, unstructured data into typed, validated values — layer by layer, at whatever depth your application requires.

The missing data layer for Rust. Progressive type coercion, automatic format detection, and fault-tolerant deserialization — built on serde, not against it.

MIT OR Apache-2.0 · Rust 1.85+ · 3 core dependencies

Install

Cargo.toml
[dependencies]
laminate = { version = "0.4", features = ["full"] }

Real-world data is messy. Laminate handles it.

main.rs
use laminate::FlexValue;

let data = FlexValue::from_json(
    r#"{"port": "8080", "debug": "true"}"#
)?;

let port: u16 = data.extract("port")?;    // "8080" -> 8080
let debug: bool = data.extract("debug")?; // "true" -> true
NEW · v0.4.1 Release notes →

FlexValue::from_llm_response pulls a JSON payload out of fenced or prose-wrapped model output before parsing; the derive now shapes string-valued enums with a #[laminate(unknown)] open fallback; and provider Usage carries OpenAI/Anthropic cache tokens.

THE ORIGIN
“I would love to see this explored in a different library specifically geared toward fault-tolerant partially successful deserialization.”

— serde maintainer, issue #464 (2017)

When serde's maintainer closed that request, he noted it belonged in a different library. Laminate is built to be that library — it doesn't replace serde, it builds on top of it, adding the progressive coercion and graceful degradation serde deliberately doesn't provide.

What's in the box

Progressive Coercion

Four levels of strictness — from exact type matching to best-effort conversion. You choose how forgiving your pipeline should be.

Learn more →

Automatic Type Detection

guess_type() identifies 20 types from raw strings — integers, dates, currencies, emails, UUIDs, IBANs, credit cards, and more — with confidence scores.

Learn more →

Graduated Diagnostics

Every coercion reports what happened, the risk level (Info/Warning/Risky), and how to tighten it. Audit your data pipeline without breaking it.

Learn more →

Domain Packs

Built-in parsers for dates (18 formats), currencies (19 symbols), medical lab values (36 analytes), identifiers (12 types with checksums), units, and geographic coordinates.

Learn more →

Provider Normalization

Parse and normalize responses from Anthropic, OpenAI, and Ollama into a unified structure. Stream SSE events incrementally.

Learn more →

Derive Macro

#[derive(Laminate)] with seven field attributes (coerce, default, overflow, rename, parse_json_string, flatten, skip), string-valued enums with a #[laminate(unknown)] fallback, and a ToolDefinition for typed LLM tool-calls.

Learn more →

Operational Modes

Lenient, Absorbing, or Strict — type-level modes that set coercion, unknown-field, and missing-field behavior at once, checked at compile time. Pick one at runtime with DynamicMode.

Learn more →

Schema + Audit

Infer a schema from a sample, attach constraints, then audit new data and get back exactly where it violates — type mismatches, missing fields, unexpected nulls, and more.

Learn more →

Sources + Tooling

Read rows from Postgres, SQLite, MySQL, and JSON/JSONL files with laminate-sql, or profile and validate from the terminal with laminate-cli (infer / audit / inspect).

Learn more →
71,915
Test cases
100%
Pass rate
8M+
Fuzz runs
3
Core dependencies
MIT / Apache-2.0
License