Home > Net >  Serde missing field error when deserializing json file
Serde missing field error when deserializing json file

Time:12-19

I can't seem to grasp why this error is happening.

Am I following the docs wrong?

This is the error I am getting and it happens with all the fields in the struct except the map:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("missing field `link`", line: 10, column: 1)', src\main.rs:22:47

This is my main.rs

use serde_json::{self, Value};
use std::{fs, collections::HashMap};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Init {
    link: String,
    page: String,
    pageid: u16,
    update_timestamp: u16,

    #[serde(flatten)]
    char_page_info: HashMap<String, Value>
}

fn main() {
    let data = fs::read_to_string("init.json").expect("Unable to read file");
    println!("{}", data);
    let p: Init = serde_json::from_str(&data).unwrap();
    println!("{:#?}", p.char_page_info); 
}

This is the init.json

{
    "char_page_info": [
        {
            "link": "",
            "page": "GGST/Jack-O/Frame_Data",
            "pageid": 27121,
            "update_timestamp": 0
        }
    ]
}

If i remove link: String, page: String, pageid: u16, update_timestamp: u16,

it doesn't throw any errors and deserializes without any hiccups.

Can someone explain to me why that is?

CodePudding user response:

It's not just link that is missing: Serde bails at the first error. link, page, and pageid, and update_timestamp are all missing. Serde looks for those fields on the top level object, and doesn't find them, since the only key present there is char_page_info. Since there can be multiple values of char_page_info (it is an array), your struct doesn't model the underlying data correctly. By fully modelling the data, we can get the expected results:

#[derive(Serialize, Deserialize, Debug)]
struct Init {
    link: String,
    page: String,
    pageid: u16,
    update_timestamp: u16,
}

#[derive(Serialize, Deserialize, Debug)]
struct Data {
    char_page_info: Vec<Init>,
}

let data = r#"{
    "char_page_info": [
        {
            "link": "",
            "page": "GGST/Jack-O/Frame_Data",
            "pageid": 27121,
            "update_timestamp": 0
        }
    ]
}"#;
println!("{}", data);
let p: Data = serde_json::from_str(&data).unwrap();
println!("{:#?}", p.char_page_info); 

(playground)

  • Related