How do y'all design your PATCH (partial update) APIs? Do you manually map `Some`/`None` to `Set`/`Unset`?

51 points Dec_32 20 comments

Say you have a model with 10 non-null fields, and you expose an API that allows partial updates on them. Apparently, in your patch payload, all fields need to be Option so that the JSON can omit the fields that it doesn't want to modify. Now your back end code looks like:

// assume we are using SeaORM
let patch = ActiveModel {
    foo: payload.foo.map(Set).unwrap_or(Unset),
    bar: payload.bar.map(Set).unwrap_or(Unset),
    qux: payload.qux.map(Set).unwrap_or(Unset),
    //...
    the_end_of_universe: payload.the_end_of_universe.map(Set).unwrap_or(Unset),
}

Is there any way you could automate this? I know that Sea-ORM failed to (fully) derive such a pattern because you cannot tell if a None is null or undefined, and thus you don't know if a None should be mapped to Unset or Set(None).

I tried to implement my own Option-like types that distinguish undefined and null, but serde decided that whether a value is missing or not is something structs should care about (using #[serde(default)] to handle it), and implementations of Deserialize are forbidden to do anything about it. You have visit_some and visit_none but never visit_missing, making enum Skippable {Some(T), Undefined} impossible to function on its own.

What should I do?