oxidecomputer / oxidecomputer/typify

parameters that are not required and nullable cannot be set to null

Open
#851 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

typify2
Dominant language
Rust
Stars
898
Forks
114
Avg merge
4h 18m
Merged PRs (30d)
14

Description

I have this schema, there are no required attributes (because it's used to patch an entry, so you can update only one element), there are so much more properties, but these two show what I mean (taken from netbox's openapi definition, which you probably cannot find online because it's auto-generated from the code at runtime) :

components:
  schemas:
    PatchedWritableInterfaceRequest:
      type: object
      description: Adds support for custom fields and tags.
      properties:
        device:
          type: integer
        lag:
          type: integer
          nullable: true
          title: Parent LAG

And the type for this is with the latest commit (7510faf9) from main :

    #[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
    pub struct PatchedWritableInterfaceRequest {
        #[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
        pub device: ::std::option::Option<i64>,
        #[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
        pub lag: ::std::option::Option<i64>,
    }

With this, I cannot make a request with {lag:null}.
It feels like that if a property is not required, it ends up being an Option<T>, and that a property being nullable also ends up being an Option<T>.
A property that is not required and nullable should probably be an Option<Option<T>> so that it can be:

  • unset (which would be None)
  • set to null, which would be Some(None)
  • set to a value would be Some(Some(123)).

For reference (and why I hve a PartialEq), the build.rs code for this is:

    let mut settings = GenerationSettings::new();
    settings.with_interface(InterfaceStyle::Builder);
    settings
        .with_derive("PartialEq")
        .with_pre_hook(quote! { |request| tracing::trace!("request {:?}", request) })
        .with_post_hook(quote! { |result| tracing::trace!("result {:?}", result) });

    let mut generator = Generator::new(&settings);

    let tokens = generator.generate_tokens(&spec)?;
    let ast = parse2(tokens)?;

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the build.rs generation settings and inspect how the generator handles the shown schema's optional and nullable properties. Generate PatchedWritableInterfaceRequest from the example, then verify that lag can be unset, explicitly serialized as null, or serialized with a value.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.