[ANN] rust_iso20022 โ€” strongly-typed ISO 20022 financial messaging for Rust

โš“ Rust    ๐Ÿ“… 2026-06-27    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 1      

surdeus

Hi everyone,

I just published rust_iso20022, a Rust SDK for ISO 20022 โ€” the financial messaging standard (MX) behind payment rails like SWIFT, SEPA, and FedNow. The whole typed model is generated directly from the official ISO 20022 XSD schemas. It's the MX-messaging counterpart to rust_iso3166.

The idea is to give you strongly-typed Rust structs for MX messages, plus XML/JSON (de)serialization, message identification, and metadata โ€” without hand-writing any of the message models.

Coverage

A typed model is generated for 722 message schemas across 32 business areas (pacs, pain, camt, acmt, reda, remt, head, auth, the card families caaa/catm/โ€ฆ, plus the securities settlement/management sese/semt/secl, trade-services tsin/tsmt/tsrv, FX fxtr, collateral colr, and more).

What it does

  • Typed models โ€” generated::<area>::<msg>::Document for every message version, e.g. pacs.008.001.08.
  • XML parse / serialize via from_xml / to_xml (backed by yaserde).
  • JSON parse / serialize via from_json / to_json (with the serde feature).
  • Auto-detect & parse โ€” detect(xml), parse_as::<T>(), or parse_auto(xml) returning an AnyMessage.
  • Per-message identity โ€” every Document implements the MxMessage trait (namespace, MxId, business area, functionality, variant, version).
  • Business Application Header (BAH / head.001) โ€” read and build.
  • Typed envelope (header + document) and a generic tree (MxNode::parse) for reading any message without pulling in its model.
  • Message catalogue โ€” every message id + namespace as static phf tables.
  • WASM / JS bindings.

Quick example

rust

use rust_iso20022::MxMessage;
use rust_iso20022::generated::any::parse_auto;

// Auto-detect and parse any supported message:
let msg = parse_auto(&xml)?;
println!("{} from {:?}", msg.message_name(), msg.mx_id().business_area);

// Or work with a known type that carries its own identity:
use rust_iso20022::generated::pacs::pacs_008_001_08::Document;

let doc: Document = rust_iso20022::from_xml(&xml)?;
let back: String  = rust_iso20022::to_xml(&doc)?;

A note on compile times

722 message modules is a lot to compile at once, so the model is gated per business area. You enable only what you need:

toml

# Just the pacs family โ€” compiles in seconds, not minutes
cargo add rust_iso20022 -F model-pacs

model-<area> pulls in one family; model enables everything. The core (MxId, BusinessArea) and the catalogue are always available without any model feature. There's also an optional cli feature exposing an iso20022 catalogue-lookup command.

A design choice worth flagging

Scalar leaf values are exposed as String rather than typed Decimal/Date. This is intentional: it's lossless (exact text, no float rounding โ€” which matters for monetary amounts) and keeps XML and JSON in sync. The optional convert feature adds typed to_decimal / to_date / to_datetime helpers when you want them.

Links

Status & feedback

This is an early release (0.1.1). I'd love feedback on the API ergonomics and on which message families people most want to see exercised in real workflows. If you have real-world MX XML that fails to round-trip, that's especially useful โ€” please open an issue. Issues and PRs welcome, and thanks for taking a look!

1 post - 1 participant

Read full topic

๐Ÿท๏ธ Rust_feed