Is your feature request related to a problem? Please describe.
The Rust client generator (rust) does not currently support the default schema element for model properties. When a property has a default value defined in the OpenAPI specification, the generated Rust model ignores it and falls back to Rust's #[derive(Default)], which uses None for Option<T> types.
For example, the petstore.yaml spec defines the Order schema with complete: default: false:
Order:
type: object
properties:
id:
type: integer
format: int64
petId:
type: integer
format: int64
quantity:
type: integer
format: int32
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
enum:
- placed
- approved
- delivered
complete:
type: boolean
default: false
The generated Rust model ignores this default:
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct Order {
#[serde(rename = "id", skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(rename = "petId", skip_serializing_if = "Option::is_none")]
pub pet_id: Option<i64>,
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
#[serde(rename = "complete", skip_serializing_if = "Option::is_none")]
pub complete: Option<bool>,
}
This means Order::default().complete returns None instead of Some(false), and deserializing JSON with a missing complete field also yields None.
In contrast, the Python generator correctly handles this default:
complete: Optional[StrictBool] = False
Describe the solution you'd like
Generate a custom Default implementation and add #[serde(default)] at the struct level when any property has a default value:
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct Order {
#[serde(rename = "id", skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(rename = "petId", skip_serializing_if = "Option::is_none")]
pub pet_id: Option<i64>,
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
#[serde(rename = "complete", skip_serializing_if = "Option::is_none")]
pub complete: Option<bool>,
}
impl Default for Order {
fn default() -> Self {
Self {
id: None,
pet_id: None,
quantity: None,
ship_date: None,
status: None,
complete: Some(false),
}
}
}
The #[serde(default)] attribute ensures that during deserialization, missing fields are populated from Order::default() rather than using None.
Describe alternatives you've considered
-
Per-field #[serde(default = "fn_name")]: This works but requires generating a separate function for each field with a default, leading to more verbose output. The struct-level #[serde(default)] approach is cleaner.
-
Post-processing the generated code: Users could manually edit the generated models, but this breaks on regeneration and defeats the purpose of code generation.
Additional context
Type mapping for defaults:
| Type |
OpenAPI default |
Rust default expression |
| string |
"foo" |
Some("foo".to_string()) |
| integer |
42 |
Some(42) |
| number |
1.234 |
Some(1.234) |
| boolean |
false |
Some(false) |
| enum |
placed |
Some(Status::Placed) |
| array |
["a", "b"] |
Some(vec!["a".to_string(), "b".to_string()]) |
Related issues:
- #3359 - [ASP.NET Core] Support default values for model properties
- #14013 - [go-server] enforcement of minimum, maximum; application of default
I'd be happy to work on a PR to implement this feature.
Is your feature request related to a problem? Please describe.
The Rust client generator (
rust) does not currently support thedefaultschema element for model properties. When a property has adefaultvalue defined in the OpenAPI specification, the generated Rust model ignores it and falls back to Rust's#[derive(Default)], which usesNoneforOption<T>types.For example, the petstore.yaml spec defines the
Orderschema withcomplete: default: false:The generated Rust model ignores this default:
This means
Order::default().completereturnsNoneinstead ofSome(false), and deserializing JSON with a missingcompletefield also yieldsNone.In contrast, the Python generator correctly handles this default:
Describe the solution you'd like
Generate a custom
Defaultimplementation and add#[serde(default)]at the struct level when any property has a default value:The
#[serde(default)]attribute ensures that during deserialization, missing fields are populated fromOrder::default()rather than usingNone.Describe alternatives you've considered
Per-field
#[serde(default = "fn_name")]: This works but requires generating a separate function for each field with a default, leading to more verbose output. The struct-level#[serde(default)]approach is cleaner.Post-processing the generated code: Users could manually edit the generated models, but this breaks on regeneration and defeats the purpose of code generation.
Additional context
Type mapping for defaults:
"foo"Some("foo".to_string())42Some(42)1.234Some(1.234)falseSome(false)placedSome(Status::Placed)["a", "b"]Some(vec!["a".to_string(), "b".to_string()])Related issues:
I'd be happy to work on a PR to implement this feature.