Есть ли способ "сгладить" перечисления для (де) сериализации в Rust? - PullRequest
1 голос
/ 24 октября 2019

У меня есть перечисление, состоящее из других перечислений, аналогичное следующему (serde производные и аннотации для краткости опущены):

enum Main {
    A(SubA),
    B(SubB),
}

enum SubA { X1, X2, X3 }
enum SubB { Y1, Y2, Y3 }

Я бы хотел использовать serde чтобы десериализовать строку, такую ​​как «X1» или «Y3», и автоматически получить Main::A(SubA::X1) или Main::B(SubB::Y3) соответственно.

Я понимаю, что serde поддерживает атрибут #[serde(transparent)] для newtypeстиль структуры, которая будет делать то, что мне нравится. Однако кажется, что он работает только на уровне структуры или перечисления, а не на уровне варианта перечисления. Есть ли способ, которым я могу автоматически получить поведение, которое я ищу? Я могу гарантировать, что не будет совпадений ни в одном из имен вариантов в любом из вложенных под-перечислений.

Помимо желания остаться в стабильной версии Rust 2018, у меня нет других ограничений на мой проект, иЯ открыт для любых предложений ящиков, которые могут помочь.

1 Ответ

1 голос
/ 24 октября 2019

Это работает в значительной степени из коробки, если вы положили serde(untagged) на внешнее перечисление и ничего особенного на внутреннее перечисление:

use serde_derive::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
enum Main {
    A(SubA),
    B(SubB),
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
enum SubA { X1, X2, X3 }

#[derive(Debug, Deserialize, Serialize, PartialEq)]
enum SubB { Y1, Y2, Y3 }

fn main() {
    let x1 = Main::A(SubA::X1);
    let y2 = Main::B(SubB::Y2);

    assert_eq!(serde_json::to_string(&x1).unwrap(), "\"X1\"");
    assert_eq!(serde_json::to_string(&y2).unwrap(), "\"Y2\"");

    assert_eq!(serde_json::de::from_str::<Main>("\"X1\"").unwrap(), x1);
    assert_eq!(serde_json::de::from_str::<Main>("\"Y2\"").unwrap(), y2);
}

...