Skip to content

[Rust] Rust client models don't correctly implement fields which are both optional and nullable. #13174

@jacob-pro

Description

@jacob-pro

From the docs:

Note: nullable is not the same as an optional parameter or an empty-valued parameter. nullable means the parameter value can be null. Specific implementations may choose to map an absent or empty-valued parameter to null, but strictly speaking these are not the same thing.

I would like to be able to distinguish between a field that has been omitted (and should not be changed), compared to a field being deliberately set to null during API update operations.

See: serde-rs/serde#1042

Current Behaviour

Schema:

schema:
  type: object
  title: UpdateRequest
  required:
    - required_nonnull
    - required_nullable
  properties:
    optional_nonnull:
      type: string
      nullable: false
    required_nonnull:
      type: string
      nullable: false
    optional_nullable:
      type: string
      nullable: true
    required_nullable:
      type: string
      nullable: true

Generated code:

#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
pub struct UpdateRequest {
    #[serde(rename = "optional_nonnull", skip_serializing_if = "Option::is_none")]
    pub optional_nonnull: Option<String>,
    #[serde(rename = "required_nonnull")]
    pub required_nonnull: String,
    #[serde(rename = "optional_nullable", skip_serializing_if = "Option::is_none")]
    pub optional_nullable: Option<String>,
    #[serde(rename = "required_nullable")]
    pub required_nullable: Option<String>,
}
Expected behaviour

The current code is correct in 3 out of the 4 cases.

  • optional_nonnull: ✅ If None is specified, then the value is skipped when serializing
  • required_nonnull: ✅ The value is always serialized and never null
  • optional_nullable: ❌ No way to distinguish between a value that has been omitted vs set to null
  • required_nullable: ✅ The value is always serialized, even if it is set to null.

Expected code generation

    #[serde(
        default
        skip_serializing_if = "Option::is_none",
        with = "::serde_with::rust::double_option",
    )]
    pub optional_nullable: Option<Option<String>>,
Suggest a fix

I will have a look at writing a PR to do this:

We need to update the generated code for the case where a field is both optional & nullable to use a double option

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions