From 5771c70396b0416b0b5a64eacef4d9bbf0342ca2 Mon Sep 17 00:00:00 2001 From: Kilerd Chan Date: Thu, 5 Feb 2026 18:22:07 +0800 Subject: [PATCH 1/2] feat: add Schematic trait support for rust_decimal::Decimal Implement Schematic trait for rust_decimal::Decimal type to enable OpenAPI schema generation. Maps Decimal to string type with "decimal" format, consistent with existing BigDecimal support. Co-Authored-By: Claude Haiku 4.5 --- gotcha/Cargo.toml | 1 + gotcha/src/openapi/schematic.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/gotcha/Cargo.toml b/gotcha/Cargo.toml index 22599e9..6076513 100644 --- a/gotcha/Cargo.toml +++ b/gotcha/Cargo.toml @@ -50,6 +50,7 @@ worker = {version = "0.5.0", features = ["http"], optional = true} thiserror = "1.0" serde_json = "1" bigdecimal = "0.4" +rust_decimal = "1.36" uuid = {version = "1.10" } regex = "1.7" diff --git a/gotcha/src/openapi/schematic.rs b/gotcha/src/openapi/schematic.rs index cea9b35..0869222 100644 --- a/gotcha/src/openapi/schematic.rs +++ b/gotcha/src/openapi/schematic.rs @@ -279,6 +279,24 @@ impl Schematic for BigDecimal { } } +impl Schematic for rust_decimal::Decimal { + fn name() -> &'static str { + "decimal" + } + + fn required() -> bool { + true + } + + fn type_() -> &'static str { + "string" + } + + fn format() -> Option { + Some("decimal".to_string()) + } +} + impl Schematic for HashSet { fn name() -> &'static str { T::name() From 56d4a1cff3211450dbeb079256b3f3e4f008d255 Mon Sep 17 00:00:00 2001 From: Kilerd Chan Date: Thu, 5 Feb 2026 18:22:13 +0800 Subject: [PATCH 2/2] test: add OpenAPI schema test for rust_decimal::Decimal Add test case validating Decimal schema generation in struct fields, covering both required and optional decimal fields. Co-Authored-By: Claude Haiku 4.5 --- gotcha/tests/pass/openapi/rust_decimal.json | 21 +++++++++++++++++++ gotcha/tests/pass/openapi/rust_decimal.rs | 23 +++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 gotcha/tests/pass/openapi/rust_decimal.json create mode 100644 gotcha/tests/pass/openapi/rust_decimal.rs diff --git a/gotcha/tests/pass/openapi/rust_decimal.json b/gotcha/tests/pass/openapi/rust_decimal.json new file mode 100644 index 0000000..60ded11 --- /dev/null +++ b/gotcha/tests/pass/openapi/rust_decimal.json @@ -0,0 +1,21 @@ +{ + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "string", + "format": "decimal" + }, + "discount": { + "type": "string", + "format": "decimal", + "nullable": true + } + }, + "required": ["name", "price"] + }, + "required": true +} \ No newline at end of file diff --git a/gotcha/tests/pass/openapi/rust_decimal.rs b/gotcha/tests/pass/openapi/rust_decimal.rs new file mode 100644 index 0000000..b46d5ad --- /dev/null +++ b/gotcha/tests/pass/openapi/rust_decimal.rs @@ -0,0 +1,23 @@ +use gotcha::openapi::schematic::Schematic; +use gotcha_macro::Schematic; +use rust_decimal::Decimal; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Schematic)] +struct Product { + name: String, + price: Decimal, + discount: Option, +} + +#[test] +fn test_decimal_schema_generation() { + let schema = Product::generate_schema(); + let json = serde_json::to_string_pretty(&schema).unwrap(); + + let expected = include_str!("rust_decimal.json"); + assert_json_diff::assert_json_eq!( + serde_json::from_str::(&json).unwrap(), + serde_json::from_str::(expected).unwrap() + ); +} \ No newline at end of file