Reputation: 23
How to properly define the data types such that the JSON de-serialize works fine with Serde/Rust for the following examples? I believe the Hashmap is the culprit somehow. Unable to tell what precisely is wrong. I hope for more complex examples involving logical and comparison operators to work as well.
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub type Single = MetadataColumnValue;
pub type Multiple = Vec<MetadataColumnValue>;
// Define the generic MetadataColumn type
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum MetadataColumnValue {
StringValue(String),
IntValue(i32),
FloatValue(f64),
// Add other types as needed
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum ComparisonOperator {
#[serde(rename = "$eq")]
Eq(Single),
#[serde(rename = "$ne")]
Ne(Single),
#[serde(rename = "$gt")]
Gt(Single),
#[serde(rename = "$gte")]
Gte(Single),
#[serde(rename = "$ge")] // Assuming $ge is the same as $gte for this example
Ge(Single),
#[serde(rename = "$lt")]
Lt(Single),
#[serde(rename = "$lte")]
Lte(Single),
#[serde(rename = "$in")]
In(Multiple),
#[serde(rename = "$nin")]
Nin(Multiple),
// Add other operators as needed
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum LogicalOperator {
#[serde(rename = "$and")]
And(Vec<Filter>),
#[serde(rename = "$or")]
Or(Vec<Filter>),
// Add other logical operators as needed
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum Filter {
Comparison {
#[serde(flatten)]
column: HashMap<String, ComparisonOperator>,
},
Logical(LogicalOperator),
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct SomeThing {
pub name: String,
pub filter: Option<Filter>,
pub count: Option<i32>,
}
fn main() {
let json_data1 = r#"
{
"name": "example",
"filter": {
"genre": { "$eq": "drama" }
},
"count": 10
}
"#;
let json_data2 = r#"
{
"name": "example",
"filter": {
"year": { "$ge": 2020 }
},
"count": 5
}
"#;
let ann1: SomeThing = serde_json::from_str(json_data1).unwrap();
let ann2: SomeThing = serde_json::from_str(json_data2).unwrap();
println!("{:?}", ann1);
println!("{:?}", ann2);
}
Compiling playground v0.0.1 (/playground)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.42s
Running `target/debug/playground`
thread 'main' panicked at src/main.rs:98:60:
called `Result::unwrap()` on an `Err` value: Error("data did not match any variant of untagged enum Filter", line: 6, column: 9)
Upvotes: 1
Views: 157
Reputation: 26767
ComparisonOperator
must be tagged. So just remove untagged
from ComparisonOperator
and it will work:
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub enum ComparisonOperator {
}
Read more on Enum representations for serde.
Upvotes: 2