Serde
Toql structs usually have a lot of Option types to make fields selectable with a query.
Let's look how to attribute them with serde for smooth interaction.
This requires the feature serde for Toql:
[dependencies]
toql = {version = "0.4", features=["serde"]}
Serializing
It's nice to omit unselected fields. This can easily achieved with #[serde(skip_serializing_if = "Option::is_none")]
Serialize example
# #![allow(unused_variables)] #fn main() { use toql::prelude::{Toql, Join}; use serde::Serialize; # #[derive(Toql, Serialize)] # struct Address { # #[toql(key)] # id: u64 # } #[derive(Toql, Serialize)] struct User { #[toql(key)] id: u64, #[serde(skip_serializing_if = "Option::is_none")] age: Option<u8>, #[serde(skip_serializing_if = "Option::is_none")] #[toql(join)] address: Option<Option<Join<Address>>> // Selectable left join } #}
Deserializing
Your server needs deserializing either
- when creating a new item
 - or when updating an existing item
 
Deserialize example:
    use toql::prelude::Toql;
    #[derive(Toql)]
    #[toql(auto_key)]
    struct User {
    
        // Serde `default` allows missing field `id` in Json
        //  Needed typically for insert and auto key
        #[serde(default)] 
        #[toql(key)]
        id: u64
        
        // No Serde attribute
        // Field must always be present in Json, but may be `null` -> `Option::None`
        // Fields that are `None` wont be updated.
        name: Option<String>
        // Never deserialize expressions
        #[serde(skip_deserializing)]  
        #[toql(sql = "(SELECT COUNT(*) From Book b WHERE b.author_id = ..id)")]
        pub number_of_books: Option<u64>,
    
        // See comment below
        #[serde(default, deserialize_with="des_double_option")]
        address: Option<Option<Join<Address>>> 
    }
Notice the double Option on the selectable left join address.
When deserializing from JSON the following mapping works:
| JSON | Rust | 
|---|---|
| undefined | None | 
| null | Some(None) | 
| value | Some(Some(value)) | 
To make this happen you need a custom deserialization function:
# #![allow(unused_variables)] #fn main() { use serde::{Deserializer, Deserialize}; pub fn des_double_option<'de, T, D>(de: D) -> Result<Option<Option<T>>, D::Error> where T: Deserialize<'de>, D: Deserializer<'de>, { Deserialize::deserialize(de).map(Some) } #}
Now you get the following:
- If you omit address in your JSON 
#[serde(default)]kicks in and you getNone. - If you send 
"addess": null, you getSome(None). - If you send 
"address: {"id": 5}", you getSome(Some(Join::Key(AddressKey{id:5}))). - If you send 
"address: {"id": 5, ...}", you getSome(Some(Join::Entity(Address{id:5, ...}))). 
Toql update will now work as expected.