I’m trying to migrate a discount function from shopify_function 0.8.x to 1.1.1.
In 0.8.x, I could use serde tagged enums for config without issues:
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "value", rename_all = "lowercase")]
pub enum DiscountValue {
Percentage(f64),
Amount(Vec<MarketWiseAmount>),
}
But in 1.1.1, this fails when used in custom_scalar_overrides:
#[query("src/run.graphql",
custom_scalar_overrides = {
"Input.discount.configuration.jsonValue" => super::Configuration,
}
)]
Error: “Enum types are not supported for deriving Deserialize ”
Enums are pretty important for modeling real-world discount configs (percentage vs. amount, min quantity vs. amount, etc.). Right now my only options seem to be:
Stay on 0.8.x
Do fragile JSON conversions with serde_json
Flatten everything to structs (lose type safety)
Has anyone found a clean workaround for this? Or is enum support planned in future releases of the crate?
Thanks in advance!
1 Like
Hirano
August 23, 2025, 11:01am
2
I am trying to implement enum using the following method. However, this code needs to be verified during the testing phase.
PS: I have tested the following code and confirmed that it works.
#[derive(Deserialize, Debug, Clone)]
#[shopify_function(rename_all = "camelCase")]
pub struct DiscountConfiguration {
pub purchase_type: Option<String>
}
impl DiscountConfiguration {
const DEFAULT_PURCHASE_TYPE: Option<String> = None;
pub fn purchase_type_enum(&self) -> Option<PurchaseType> {
self
.purchase_type
.as_ref()
.and_then(|s| PurchaseType::from_str(s))
}
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum PurchaseType {
OneTimePurchase,
Subscription,
Both,
}
impl PurchaseType {
pub fn from_str_custom(s: &str) -> Option<Self> {
match s {
"ONE_TIME_PURCHASE" => Some(Self::OneTimePurchase),
"SUBSCRIPTION" => Some(Self::Subscription),
"BOTH" => Some(Self::Both),
_ => None,
}
}
}
Next is an examples of usage.
fn is_purchase_type_line(&self, line: &Lines) -> bool {
match self.configuration.purchase_type_enum() {
None | Some(PurchaseType::Both) => true,
Some(PurchaseType::OneTimePurchase) => line.selling_plan_allocation().is_none(),
Some(PurchaseType::Subscription) => line.selling_plan_allocation().is_some(),
}
}