Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking change to deserialization in 0.27.0 - Err value: Custom("missing field ...") #558

Closed
spazm opened this issue Feb 20, 2023 · 6 comments
Labels
question serde Issues related to mapping from Rust types to XML

Comments

@spazm
Copy link

spazm commented Feb 20, 2023

Unexpected breaking change to deserialization behavior. (AKA a bug was fixed 馃槃 )

Updating to current v0.27.1 caused my deserializer library to fail with a Custom("missing field '...').
Note: the error message uses backticks (`) rather than single quotes ('), but those are hard to write in markdown. This error did not make it clear how to find the problem. Updating from v0.23.0 to v0.26.0 was transparent. Updating to v0.27.1 caused errors.

After a considerable amount of digging, I found that this was an intentional change. I don't know where I should have looked to find information about the change and how to migrate my code. The documentation for quick_xml::de was updated with the new syntax, but it doesn't show that the syntax changed in this version.

The change:
Deserialization used to treat attributes and elements equivalently when de-serializing. This was changed in v0.27.0, as part of the serializer rewrite in #490 . Specifically commit 8b50c64

The description of #490 contains this "Notable Change" notice

Change how attributes is defined. Now attribute should have a name started with @ character. Without that fields serialized as elements and can be deserialized only from elements. Deserialization from element or from attribute into one field is not possible anymore. It's a weird wish anyway

Prior to 0.27, these two documents could both be deserialized into the same struct definition:

<a b="1"><c>2</c></a>
<a><b>1</b><c>2</c></a>
#[derive(Debug, Deserialize, PartialEq)]
struct A {
  b: String,
  c: String,
}

With the change to v0.27 those two documents are distinct and deserialize into different structures. Attributes now have a @ prefix and will need to a serde(rename) to convert to a valid type name. The two example documents now require slightly different struct definitions:

// <a b="1"><c>2</c></a>

#[derive(Debug, Deserialize, PartialEq)]
struct A {
  #[serde(rename = "@b")]
  b: String,
  c: String,
}
// <a><b>1</b><c>2</c></a>

#[derive(Debug, Deserialize, PartialEq)]
struct A {
  b: String,
  c: String,
}
@spazm
Copy link
Author

spazm commented Feb 20, 2023

I hope this helps you, random future github user, if you find this issue while searching for the meaning a Custom("missing field ...") error in code that worked prior to updating.

Hey maintainers, thanks for your work on this module!!
And especially for bringing it back from stalled status with new collaborators, woo!!

@spazm
Copy link
Author

spazm commented Feb 20, 2023

I am excited that this new nomenclature will let me describe which struct fields should be serialized as attributes vs elements.

I did enjoy the robust flexibility of parsing either form with the same struct code. XML that doesn't have an associated DTD can easily get munged between attr and elems during read-edit-export processes.

@Mingun Mingun added question serde Issues related to mapping from Rust types to XML labels Feb 20, 2023
@Mingun
Copy link
Collaborator

Mingun commented Feb 20, 2023

Well, the changelog mentions this change, but maybe not highlights it very well as it should. In any case, I glad that you found the root cause and shared your experience :)

@Mingun Mingun closed this as completed Feb 20, 2023
@spazm
Copy link
Author

spazm commented Feb 20, 2023

馃憤

@istellino-chub
Copy link

@spazm @Mingun is there a way to make that all attributes works as in the past version using #serde(rename.. or somehow? because when using quick-xml version 22.0 attributes flow normally and now with version 0.27 no

@Mingun
Copy link
Collaborator

Mingun commented Aug 30, 2023

You should name your attributes starting with @ character, using #[serde(rename = "@...")] or analogues. The @ convention works also for tag and content names in enums.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question serde Issues related to mapping from Rust types to XML
Projects
None yet
Development

No branches or pull requests

3 participants