Serde expected value at line 1 column 1


#1

Hi all,

I have a wired problem with serde_json. I have a vector with a struct, that I would like to safe and load from a json file.

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

impl Foo {
    pub fn new() -> Foo {
        Foo { name: String::new(), }
    }
}

and I use these to serialize:

pub fn encode(definitions: &Vec<Foo>) -> String {
    match serde_json::to_string(definitions) {
        Ok(j) => { return j; },
        Err(_) => { return String::new(); },
    }
}

pub fn decode(data: &str) -> Vec<Foo> {
    println!("dec: {}", data);

    match serde_json::from_str(data) {
        Ok(p) => { return p; },
        Err(e) => {
        	println!("err: {}", e);
        	return Vec::new(); 
        },
    }
}

furthermore I have a simple test for this:

#[test]
fn encode_decode() {
    let foos = vec!(Foo::new(),Foo::new());
    let enc = encode_episodes(&foos);
    let dec = decode_episodes(&enc);

    assert_eq!(2, eps.len());
    assert_eq!(2, dec.len());
}

So far everything works as expected. Note, that I output the data-string in the “decode” function. I take that output and save it into a file. When I load that file and use decode in my app, serde can no longer read the string and panics with “expected value at line 1 column 1”. It does not seam to matter what is in the file, I always get the same result. All I do in my app is:

    let mut file = File::open("path/to/file.cfg").unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();

    let def = decode(&contents);
    println!("def: {:?}", def);

Again “decode” outputs the string it should turn into a vector and it looks identical. However, serde just panics.

Does anyone have an idea what is going wrong? Or how could I debug the problem?


#2

Do you have leading whitespace in the string? (Try decode(contents.trim()))


#3

Again “decode” outputs the string it should turn into a vector and it looks identical.

If the simple encode_decode test works, there is no way it would then fail if given the same string round-tripped through a file. So you will need to identify what is different between the string that works and the string that does not work – and what is causing that difference when using a file.


#4

Thanks for the replies.

@birkenfeld
I get the same result though. I am currently trying the same with an alternative approach by wrapping my struct so that I don’t have to use a vector directly. Maybe it has some problem with that.

pub struct Collection {
    collection: Vec<Foo>,
}

I haven’t seen anything in the doc that would suggest it’s necessary. I’ll see what happens :slight_smile:

@dtolnay
I use copy paste… They are identical. Unless the encoding of the file (I use UTF-8) is important?


#5

Leading whitespace is irrelevant. Your new Collection will be slightly different serialized representation from Vec<Foo> (it will look like {"collection": [<item 1>, <item 2>, ...]}) but should not be necessary.

At this point more of the code (or your json file) needs to be seen to diagnose the problem.

Unless the encoding of the file (I use UTF-8) is important?

JSON doesn’t support UTF-8. It must be encoded as unicode escape sequences in ASCII, but serde will have done this for you. (of course, the resulting file is valid UTF-8, but it is also valid ASCII)


#6

I use copy paste… They are identical.

If decode(s1) succeeds and decode(s2) fails then s1 and s2 are not the same string.


#7

The generated output looks like this:

[{"name":""},{"name":""}]

I copy paste it into the file. The app outputs the string again exactly the same way. I use serde_jason within the same app with other files of the same encoding. When it’s not an array, it seams to work just fine.


#8

I’m going to go out on a limb here;

  • what operating system/text editor do you use?
  • can you try the following commands and tell me what you see? (type the commands, do not copy and paste):
cargo install ripgrep
rg '\[' path/to/file.json

#9

Since the argument from dtolnay is sound and logical I decided to delete the offending file and recreate a new one, in which I once again copied the exact same output. For whatever reason it work now as expected…

Some how the first file must have gotten corrupted. Which is wired because any text editor I used to check the file did not see a problem.

I keep encountering wired issues like this when using rust. Not sure why… :slight_smile: Anyway, I consider the problem solved. Thanks dtolnay for insisting that the simplest solution should be right.


#10

Thanks for the reply ExpHP,
I think the problem is solved. The file was corrupted somehow (see my prev answer).