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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding 0 elements in to a Vec gives "custom: missing field $value" error #188

Open
nikclayton opened this issue Oct 12, 2022 · 2 comments

Comments

@nikclayton
Copy link

tl;dr: If an element can contain 0-N child elements, it's not sufficient to specify the child elements in a struct field of type Vec. You have to wrap the Vec in an Option. I found this to be counterintuitive.

I'm not sure if this is a software bug or an issue that should be more clearly explained in the documentation.

Longer:

Consider the following (it's a snippet from an Android resources file):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Theme" parent="Theme.AppCompat" />

    <style name="Theme.Default">
        <item name="colorPrimary">@color/default_backgroundColorTouched</item>
        <item name="colorPrimaryDark">@color/default_backgroundColorHighlighted</item>
        ....
    </style>
</resources>
  • resources contains 0-N style elements (this example contains > 0, but 0 is possible)
  • style elements have a mandatory name and optional parent attribute
  • style elements contain 0-N item elements with mandatory name attributes

My initial attempt at modelling this was:

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Resources {
    #[serde(rename = "$value")]
    styles: Vec<Style>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Style {
    name: String,
    parent: Option<String>,
    #[serde(rename = "$value")]
    items: Vec<Item>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
}

My expectation was that any style elements with no content (i.e., the first one), would parse correctly, giving a Style.items field of length 0.

You get an error instead, "custom: missing field $value`", which is not very helpful.

The fix is to explicitly mark the items as optional, by changing the Style definition to:

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Style {
    name: String,
    parent: Option<String>,
    #[serde(rename = "$value")]
    items: Option<Vec<Item>>,  // <-- Option added here
}

I can see arguments both ways for this, which is why I'm not sure this is a software bug, but either way, I do think this should be called out in the documentation.

@pavelskipenes
Copy link

a vector can have 0 elements so it should be a valid state

@marcelbuesing
Copy link

Another workaround is adding a default.

#[serde(default, rename = "$value")]
items: Vec<Item>,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants