#serde-json #struct #instance #deserialize-json #data #onto #serde-default

serde-deserialize-over

Deserialize structs onto existing struct instances via serde

2 releases

0.1.1 Jun 7, 2022
0.1.0 Feb 27, 2022

#1969 in Encoding

MIT/Apache

17KB
326 lines

Traits and macros for deserializing data onto an existing instance of a struct via serde. It is somewhat like a more featureful version of adding #[serde::default(...)] annotations everywhere except that it is able to use runtime data instead of hardcoded defaults.

Usage

The main trait for this crate is the DeserializeOver trait and its corresponding derive macro. It works analogously to serde's Deserialize trait except that struct fields that are not present within the data being deserialized keep their values as is.

For a simple struct, this ends up looking something like this:

use serde_deserialize_over::DeserializeOver;

#[derive(DeserializeOver)]
struct MyStruct {
    pub a: String,
    pub b: i32
}

let json = r#"{ "a": "test" }"#;
let mut inst = MyStruct {
    a: "a string".to_owned(),
    b: 32
};

let mut de = Deserializer::new(StrRead::new(json));
inst.deserialize_over(&mut de)
    .expect("Failed to deserialize JSON");

assert_eq!(inst.a, "test");
assert_eq!(inst.b, 32);

Here, the serialized json only has a value for the a field so when it gets deserialized over the existing instance the a field is updated while the b field remains unchanged.

Nested Structs

By default, the fields of the struct are deserialized using serde's Deserialize. This means that, by default, nested structs must be deserialized in entirety and cannot be deserialized on top of existing data. To mark that subfields should instead be deserialized via DeserializeOver the derive macro supports the #[deserialize_over] attribute.

use serde_deserialize_over::DeserializeOver;

#[derive(DeserializeOver, Default)]
struct Inner {
    a: i32,
    b: i32
}

#[derive(DeserializeOver, Default)]
struct Outer {
    #[deserialize_over]
    inner: Inner,
    c: i32
}

let json = r#"{ "inner": { "b": 5 } }"#;
let mut inst = Outer::default();

let mut de = Deserializer::new(StrRead::new(json));
inst.deserialize_over(&mut de)
    .expect("Failed to deserialize JSON");

assert_eq!(inst.inner.a, 0);
assert_eq!(inst.inner.b, 5);
assert_eq!(inst.c, 0);

Extras

This crate also provides the DeserializeInto extension trait on all serde Deserializers which takes the operands in the other order.

use serde_deserialize_over::{DeserializeOver, DeserializeInto};

#[derive(DeserializeOver, Default)]
struct MyStruct {
    pub a: String,
    pub b: i32
}

let json = r#"{ "a": "test" }"#;
let mut inst = MyStruct::default();

let mut de = Deserializer::new(StrRead::new(json));
de.deserialize_into(&mut inst)
  .expect("Failed to deserialize JSON");

assert_eq!(inst.a, "test");
assert_eq!(inst.b, 0);

Dependencies

~4MB
~79K SLoC