{"id":1180,"hash":"d2689857c18ecb50549d3fa45ee3be0c5068f563d6a10f9a696ddfdb0337eaa9","pattern":"&quot;invalid type: map, expected a sequence&quot; when deserializing a nested JSON structure with Serde","full_message":"I am trying to poll the GitHub API for issues and print them out. To do so, I need to deserialize a nested JSON structure that I receive from a cURL GET request.\n\nI am trying to get the url for all the objects in the items array:\n\n{\n \"total_count\": 4905,\n \"incomplete_results\": false,\n \"items\": [\n    {\n     \"url\": \"https://api.github.com/repos/servo/saltfs/issues/789\",\n     \"repository_url\": \"https://api.github.com/repos/servo/saltfs\",\n     \"labels_url\": \n   \"https://api.github.com/repos/servo/saltfs/issues/789/labels{/name}\",\n  \"comments_url\": \"https://api.github.com/repos/servo/saltfs/issues/789/comments\",\n  \"events_url\": \"https://api.github.com/repos/servo/saltfs/issues/789/events\",\n  \"html_url\": \"https://github.com/servo/saltfs/issues/789\",\n  \"id\": 293260512,\n  \"number\": 789,\n  \"title\": \"Stop setting $CARGO_HOME to its default value\",\n  \"user\": {\n    \"login\": \"SimonSapin\",\n    \"id\": 291359,\n    \"avatar_url\": \"https://avatars0.githubusercontent.com/u/291359?v=4\",\n    \"gravatar_id\": \"\",\n    \"url\": \"https://api.github.com/users/SimonSapin\",\n    \"html_url\": \"https://github.com/SimonSapin\",\n    \"followers_url\": \"https://api.github.com/users/SimonSapin/followers\",\n    \"following_url\": \"https://api.github.com/users/SimonSapin/following{/other_user}\",\n    \"gists_url\": \"https://api.github.com/users/SimonSapin/gists{/gist_id}\",\n    \"starred_url\": \"https://api.github.com/users/SimonSapin/starred{/owner}{/repo}\",\n    \"subscriptions_url\": \"https://api.github.com/users/SimonSapin/subscriptions\",\n    \"organizations_url\": \"https://api.github.com/users/SimonSapin/orgs\",\n    \"repos_url\": \"https://api.github.com/users/SimonSapin/repos\",\n    \"events_url\": \"https://api.github.com/users/SimonSapin/events{/privacy}\",\n    \"received_events_url\": \"https://api.github.com/users/SimonSapin/received_events\",\n    \"type\": \"User\",\n    \"site_admin\": false\n  },\n  \"labels\": [\n    {\n      \"id\": 341722396,\n      \"url\": \"https://api.github.com/repos/servo/saltfs/labels/E-easy\",\n      \"name\": \"E-easy\",\n      \"color\": \"02e10c\",\n      \"default\": false\n    }\n  ],\n  \"state\": \"open\",\n  \"locked\": false,\n  \"assignee\": null,\n  \"assignees\": [\n\n  ],\n  \"milestone\": null,\n  \"comments\": 0,\n  \"created_at\": \"2018-01-31T18:16:09Z\",\n  \"updated_at\": \"2018-01-31T18:16:49Z\",\n  \"closed_at\": null,\n  \"author_association\": \"MEMBER\",\n  \"body\": \"In `buildbot/master/files/config/environments.py` we set `CARGO_HOME` to Cargo’s default value. Now that `mach` does not set it (since https://github.com/servo/servo/pull/19395), this has no effect. We can remove these lines.\",\n  \"score\": 1.0\n},\n{\n  \"url\": \"https://api.github.com/repos/servo/servo/issues/19916\",\n  \"repository_url\": \"https://api.github.com/repos/servo/servo\",\n  \"labels_url\": \"https://api.github.com/repos/servo/servo/issues/19916/labels{/name}\",\n  \"comments_url\": \"https://api.github.com/repos/servo/servo/issues/19916/comments\",\n  \"events_url\": \"https://api.github.com/repos/servo/servo/issues/19916/events\",\n  \"html_url\": \"https://github.com/servo/servo/issues/19916\",\n  \"id\": 293237180,\n  \"number\": 19916,\n  \"title\": \"Use a macro to create null-terminated C strings\",\n  \"user\": {\n    \"login\": \"jdm\",\n    \"id\": 27658,\n    \"avatar_url\": \"https://avatars1.githubusercontent.com/u/27658?v=4\",\n    \"gravatar_id\": \"\",\n    \"url\": \"https://api.github.com/users/jdm\",\n    \"html_url\": \"https://github.com/jdm\",\n    \"followers_url\": \"https://api.github.com/users/jdm/followers\",\n    \"following_url\": \"https://api.github.com/users/jdm/following{/other_user}\",\n    \"gists_url\": \"https://api.github.com/users/jdm/gists{/gist_id}\",\n    \"starred_url\": \"https://api.github.com/users/jdm/starred{/owner}{/repo}\",\n    \"subscriptions_url\": \"https://api.github.com/users/jdm/subscriptions\",\n    \"organizations_url\": \"https://api.github.com/users/jdm/orgs\",\n    \"repos_url\": \"https://api.github.com/users/jdm/repos\",\n    \"events_url\": \"https://api.github.com/users/jdm/events{/privacy}\",\n    \"received_events_url\": \"https://api.github.com/users/jdm/received_events\",\n    \"type\": \"User\",\n    \"site_admin\": false\n  },\n  \"labels\": [\n    {\n      \"id\": 89384911,\n      \"url\": \"https://api.github.com/repos/servo/servo/labels/C-assigned\",\n      \"name\": \"C-assigned\",\n      \"color\": \"02d7e1\",\n      \"default\": false\n    },\n    {\n      \"id\": 15997664,\n      \"url\": \"https://api.github.com/repos/servo/servo/labels/E-easy\",\n      \"name\": \"E-easy\",\n      \"color\": \"02e10c\",\n      \"default\": false\n    },\n    {\n      \"id\": 135307111,\n      \"url\": \"https://api.github.com/repos/servo/servo/labels/I-cleanup\",\n      \"name\": \"I-cleanup\",\n      \"color\": \"e11d21\",\n      \"default\": false\n    }\n  ],\n  \"state\": \"open\",\n  \"locked\": false,\n  \"assignee\": null,\n  \"assignees\": [\n\n  ],\n  \"milestone\": null,\n  \"comments\": 3,\n  \"created_at\": \"2018-01-31T17:04:06Z\",\n  \"updated_at\": \"2018-01-31T22:03:56Z\",\n  \"closed_at\": null,\n  \"author_association\": \"MEMBER\",\n  \"body\": \"When we write them by hand (eg. `b\\\"some string\\\\0\\\"`), we invariably get them wrong in ways that are tricky to notice (https://github.com/servo/servo/pull/19915). We should use a macro like this instead:\\r\\n```rust\\r\\nmacro_rules! c_str {\\r\\n    ($str:expr) => {\\r\\n        concat!($str, \\\"\\\\0\\\").as_bytes()\\r\\n    }\\r\\n}\\r\\n```\\r\\nThis would allow us to write code like `(c_str!(\\\"PEParseDeclarationDeclExpected\\\"), Action::Skip)` instead of https://github.com/emilio/servo/blob/d82c54bd3033cc3277ebeb4854739bebe4e20f2f/ports/geckolib/error_reporter.rs#L237. We should be able to clean up all of the uses in that file.\\r\\n\\r\\nNo need to run any automated tests; if it builds with `./mach build-geckolib`, then it's good enough for a pull request.\",\n  \"score\": 1.0\n}\n]}\n\nMy request function makes a cURL request and receives the above JSON. I then use serde_json to deserialize the JSON\n\nmain.rs\n\nextern crate serde;\n#[macro_use]\nextern crate serde_derive;\nextern crate serde_json;\n\nmod engine;\nmod server;\nuse engine::request;\nuse std::string::String;\nuse self::serde_json::{Error, Value};\n\n#[derive(Serialize, Deserialize)]\n","ecosystem":"cargo","package_name":"json","package_version":null,"solution":"Have a look at this part of your JSON input data:\n\n{\n  ...\n  \"items\": [\n    {\n      ...\n      \"title\": \"Stop setting $CARGO_HOME to its default value\",\n      ...\n    }\n  ]\n}\n\nThe top-level data structure is a JSON map, so in Rust this will be represented as a struct. I will use your name Obj.\nThe top-level JSON map has a key called \"items\" so in Rust this will be a field items inside the Obj struct.\nThe value of \"items\" in the map is a JSON array, so in Rust let's use a Vec.\nEach element in the JSON array is a JSON map so in Rust we need a struct for those. We can call it Issue.\nEach issue has a JSON key called \"title\" so this will be a field title inside the Issue struct.\nThe value of \"title\" is a JSON string so we can use Rust's String type for the field.\n\n#[derive(Deserialize, Debug)]\nstruct Obj {\n    items: Vec<Issue>,\n}\n\n#[derive(Deserialize, Debug)]\nstruct Issue {\n    title: String,\n}\n\nfn main() {\n    let j = /* get the JSON data */;\n\n    let issues = serde_json::from_str::<Obj>(j).unwrap();\n    for i in issues.items {\n        println!(\"{:#?}\", i);\n    }\n}","confidence":0.95,"source":"stackoverflow","source_url":"https://stackoverflow.com/questions/48595735/invalid-type-map-expected-a-sequence-when-deserializing-a-nested-json-struct","votes":28,"created_at":"2026-04-19T04:52:32.440459+00:00","updated_at":"2026-04-19T04:52:32.440459+00:00"}