xml
xml copied to clipboard
Preserve order while deserializing
Assume the following xml:
<parent>
<objA/>
<objB/>
<objA/>
</parent>
How can I deserialize this in a fashion that preserves the order 'objA' 'objB' 'objA'?
Deserializing into a Vec<ObjA> and a Vec<ObjB> would not preserve the information that the single ObjB was deserialized between the other two.
I guess in this case an enum like enum Obj { ObjA, ObjB}, and then a Vec<Obj> would make sense, but from what I saw in the tests this only works when the xml looks like <obj xsi:type="ObjA"> etc.
Is there a good way to do this (without deserializing the whole parent manually)?
Sequences in XML are hard :) That's why I went with only accepting the xsi:type method for now.
What do you think about the following structure, similar to how it's done for inner text by using $value?
enum Obj { ObjA, ObjB }
struct Parent {
#[serde(rename="$sequence")]
data: Vec<Obj>,
}
@oli-obk Looks good to me! As a full feature, I would expect this method to also extend to cases like the following:
enum Obj { ObjA, ObjB }
enum Foo { FooA, FooB }
struct Parent {
#[serde(rename="$sequence")]
data_obj: Vec<Obj>,
#[serde(rename="$sequence")]
data_foo: Vec<Foo>,
}
to deserialize xml like:
<parent>
<objA/>
<fooA/>
<fooB/>
<objB/>
<objA/>
<fooA/>
</parent>
With the obvious semantics. Maybe a new attribute like #[serde(sequence)] would be appropiate for this case. Using #[serde(rename="$sequence")] looks kind of like a hack, even though it's only different syntax for the same result.
That's not possible in serde without first parsing the entire subtree. I don't really want to support interleaved sequences.
In that case the solution you proposed sounds good to me. I also don't have a use case for the interleaved example I wrote, so it's not something I actually encountered the need for.