Is there a reasonably simple way to use serde/serde_json to take an existing struct and update only those fields that are present in the JSON? This basically amounts to setting a default value at runtime rather than at compile time by implementing the Default trait or a default value generator function.
This seems like a really common use case when you have a RESTful API where you want to submit updates to state, modifying only specified fields and leaving unspecified fields unchanged.
I could do it by deserializing to the dynamic Value type and then doing a big match or if/else block to update fields, but that's verbose and ugly. I'm wondering if serde has anything to handle this.
Serde doesn't support anything like this. If I needed to do it, I would maybe create a parallel structure where all of the fields are optional:
use serde::Deserialize;
#[derive(Deserialize)]
pub struct MyData {
foo: String,
bar: u64,
wibble: bool,
}
#[derive(Deserialize)]
pub struct MyDataPatch {
foo: Option<String>,
bar: Option<u64>,
wibble: Option<bool>,
}
impl MyData {
pub fn patch(&mut self, update: MyDataPatch) {
if let Some(foo) = update.foo {
self.foo = foo;
}
if let Some(bar) = update.bar {
self.bar = bar;
}
if let Some(wibble) = update.wibble {
self.wibble = wibble;
}
}
}
This is more code duplication, but less runtime overhead.
If I had a lot of these, then I'd generate all of that with a macro, rather than write it by hand. You could do that with a derivable trait, something like:
trait Patch {
type Patch; // Self with all optional fields
fn patch(&mut self, patch: &Self::Patch);
}