Closed L0g4n closed 4 years ago
I think you should use #[serde(untagged)]
for the enum to do that. See https://serde.rs/container-attrs.html for details.
Thanks, that worked. Next time, I'mma first check the serde docs.
I disagree with the suggestion to simply use #[serde(untagged)]
, since serde_pickle
handles the default externally-tagged enum representation differently from other serde libraries I've personally encountered.
For example, I took serde_yaml
and serde_json
and used their to_string
function, while for serde_pickle
I pickled with the pickle 3 format, unpickled in Python 3 and put the result through print()
.
#[derive(Serialize)]
enum Foo {
Struct { a: i32 },
NewType(i32),
Tuple(i32, u32),
Unit,
}
fn values() -> Vec<Foo> {
vec![
Foo::Struct { a: 1 },
Foo::NewType(2),
Foo::Tuple(3, 4),
Foo::Unit,
]
}
[{"Struct":{"a":1}},{"NewType":2},{"Tuple":[3,4]},"Unit"]
---
- Struct:
a: 1
- NewType: 2
- Tuple:
- 3
- 4
- Unit
[('Struct', {'a': 1}), ('NewType', 2), ('Tuple', [3, 4]), ('Unit',)]
I think serde-pickle
should follow the example of serde_yaml
and serde_json
, and (de)serialize like:
[{'Struct':{'a':1}},{'NewType':2},{'Tuple':[3,4]},'Unit']
Furthermore, if you use a python YAML or JSON library to load the above YAML or JSON examples, it'll produce the same output I'd expect serde-pickle
to emit. (This is actually my use case, where a python script and a Rust program exchange data that is also distributed as YAML files).
Just for clarification, @Palladinium 's comment isn't applicable here (but it is a legitimate issue, see #9). Whether serde-pickle uses dicts or tuples for externally tagged enum representation, it would in no case work with the @L0g4n 's data without using #[serde(untagged)]
.
@birkenfeld I already thought of that; This seems more like a internal consistency issue for serde libraries.
I am currently trying to improve my deserialization process by making it more robust, i.e. it should handle another pickle format where one data field is missing.
Thus, my index datastructure that is the main entry point for the deserilization looks like this:
As you can imagine
RpaEntryNew
is an enum with two variants, one has three fields, and in the other variant theprefix
field is missing:So, when I am trying to decode the whole thing, it failed as expected since I do not know how to tell the library which variant to decode to:
The error message is the one in the title.
Do you happen to know how to make the whole process possible? Basically trying to decode the first variant of the enum and if that fails the other one?