The purpose of the DeserializeFlat derive macro is to avoid the nested JSON representation of enum tuple variants. This is really important when we want integrate with external services/apps like the Keplr wallet that expect an exact message format. We can't simply not utilize tuple variants as this is how reusable contract components are implemented in the derive-contract
macro.
A practical example is trying to create a SecretNetwork viewing key via Keplr. Keplr expects the contract to accept the following message: { set_viewing_key: { key: "my_key", padding: null } }
, which would require the handle message enum in our contract to have a variant that looks like this:
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
SetViewingKey {
key: String,
padding: Option<String>,
}
}
We can avoid implementing this logic in our contract by using Fadroma's auth module and including it in the contract definition. However, the resulting message generated by the derive-contract
macro will look something like this:
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
Auth(AuthHandleMsg)
}
making the JSON that the contract actually accepts to be this: { auth: { set_viewing_key: { key: "my_key", padding: null } } }
.
DeserializeFlat
provides a custom implementation of the serde::de::Deserialize
trait that tries to deserialize the incoming JSON as the standard derive(Deserialize)
would first and if that fails, it tries to deserialize each of the tuple enum variants directly (in the above example that would the AuthHandleMsg
type).
The current implementation of this macro makes use of serde_json
's Value type which defeats the entire purpose of the serde_json_wasm
crate to not use dynamic memory allocation so this is not really usable in its current state. It also doesn't actually work, since calls to deserialize_any
are forbidden in serde_json_wasm
and this method is called by the serde_json::Value
type.
How can the current logic be implemented without using serde_json
or ideally, not having knowledge of what Deserializer
implementation is actually being used. Alternative ideas are very welcome as well!