Q: Is it possible to diff a struct where one of the fields is serde_json::Value
I want to ensure that the data is proper json when ser/de, so I made the struct_value a serde_json::Value. However, if I try to diff it I get the following JsonValue: Diff is not satisfied
#[derive(Deserialize, Debug, Clone, Serialize, PartialEq, Diff)]
pub struct Field {
pub r#type: PostgresTypes,
#[serde(default = "default_false")]
pub unique: bool,
#[serde(default = "default_false")]
pub required: bool,
#[serde(default = "default_false")]
pub primary: bool,
#[serde(default = "default_empty_json")]
pub metadata: Option<serde_json::Value>,
}
So I've had a chance now to think about this, there's basically two options. I would probably create a wrapper struct for arbitrary json values, and implement Diff on this. The diff implementation would basically look like:
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
#[serde(transparent)]
struct ArbitraryJson(Value);
impl Diff for ArbitraryJson {
type Repr = Option<Value>;
fn diff(&self, other: &Self) -> Self::Repr {
if self != other {
Some(other.clone())
} else {
None
}
}
fn apply(&mut self, diff: &Self::Repr) {
if let Some(diff) = diff {
*self = diff.clone()
}
}
fn identity() -> Self {
Default::default()
}
}
Alternatively, you can wrap it in a Cow, which works pretty much the same way (and likewise doesn't require T to implement Diff), but I think you have to be bothered to specify a lifetime for that.
What I'd like to do going forward, but will take some more time to refine, is highly generic diffing. That means a user should be able to specify which method of diffing they want to use for individual struct fields, instead of assuming that one type has only one diff method. This way, if a type satisfies some trait bounds, we can use a certain diff method on it without ever manually implementing Diff on that type. The first example would be this kind of "equality + clone" check