Serde/rust десериализует JSON в Hashmap

Как правильно определить типы данных, чтобы десериализация JSON нормально работала с Serde/Rust для следующих примеров? Я считаю, что в этом виноват Hashmap. Невозможно сказать, что именно не так. Я надеюсь, что более сложные примеры, включающие логические операторы и операторы сравнения, также будут работать.

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)

Наличие rename в перечислении untagged не имеет никакого смысла, поскольку untagged означает, что вы не используете имя (тэг).

kmdreko 05.06.2024 13:58
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
1
1
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ComparisonOperator необходимо отметить. Так что просто удалите untagged из ComparisonOperator и всё заработает:

#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub enum ComparisonOperator {
}

Подробнее читайте в разделе Представления перечислений для serde.

Другие вопросы по теме