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

Cannot deserialize struct variant using sequence #1049

Open
szymek156 opened this issue Jul 6, 2023 · 3 comments
Open

Cannot deserialize struct variant using sequence #1049

szymek156 opened this issue Jul 6, 2023 · 3 comments

Comments

@szymek156
Copy link

Hello I've encounter following problem,

Having enum like this:

#[derive(Deserialize)]
enum Filter {
    EQ { property: String, value: String },
}

I cannot deserialize it using sequence:

#[derive(Deserialize)]
struct Req {
    filter: Filter,
}

let req: Req = serde_json::from_value(json!({
    "filter": {
        "EQ" : ["a", "b"]
    }
}).unwrap()

Error:

invalid type: sequence, expected struct variant

However extracting variant body to a struct, works well:

#[derive(Deserialize)]
struct EQ {
    property: String, value: String
}
#[derive(Deserialize)]
enum Filter {
    EQ(EQ),
}

// this doesn't panic:
let a: Req = serde_json::from_value(json!({
            "filter" : {
                "EQ": ["a", "b"]
            }
        }))
        .unwrap();

Used crates:

serde = { version = "1.0.130" }
serde_json = {version = "1.0.72" , features = ["preserve_order"]}

Full test for reproduction:

  #[test]
  fn deserialize_enum() {
      #[derive(Deserialize)]
      struct EQ {
          property: String,
          value: String,
      }
      #[derive(Deserialize)]
      enum FilterTuple {
          EQ(EQ),
      }

      #[derive(Deserialize)]
      enum FilterStruct {
          EQ { property: String, value: String },
      }

      #[derive(Deserialize)]
      struct Req {
          filter_tuple: FilterTuple,
          filter_struct: FilterStruct,
      }

      let _: Req = serde_json::from_value(json!({
          "filter_tuple" : {
              "EQ": {
                  "property": "a",
                  "value": "b"
              }
          },
          "filter_struct" : {
              "EQ": {
                  "property": "a",
                  "value": "b"
              }
          }
      }))
      .unwrap();

      let _: Req = serde_json::from_value(json!({
          "filter_tuple" : {
              "EQ": ["a", "b"]
          },
          "filter_struct" : {
              "EQ": ["a", "b"]
          }
      }))
      .unwrap();
  }
@Mingun
Copy link

Mingun commented Jul 6, 2023

This would be fixed by serde-rs/serde#2465

@dtolnay
Copy link
Member

dtolnay commented Jul 30, 2023

This is a serde_json issue.

Deserializing the same data structure using from_str (instead of from_value) succeeds.

This is unrelated to serde-rs/serde#2465 which involves untagged and adjacently tagged enums. The code above does not use untagged or adjacently tagged enums.

@dtolnay dtolnay transferred this issue from serde-rs/serde Jul 30, 2023
@jaques-sam
Copy link

jaques-sam commented Oct 27, 2023

Deserializing the same data structure using from_str (instead of from_value) succeeds.

I encountered the same issue. What I need to do to circumvent this issue is by converting the Value back to a string (using to_string() and pass it back to from_str. Which eventually makes my code deserialize my object twice :(
Like so:

let deserialized: Value = serde_json::from_str(raw_json).unwrap();
... // do some validation
let object: MyType = serde_json::from_value(deserialized).unwrap();

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

Successfully merging a pull request may close this issue.

4 participants