Dykeiichi
Dykeiichi

Reputation: 21

serde_json adding an extra '}'

I have a problme serializing/desserializing an struct with serde_json in rust, i had used the impl's (dont used derive) that are on serde_json:ser and serde_json:de, but something is happening when i try to write it in a file, i hava thread (this is the unique thread that open that file) that is in a loop saving some data to a file named "config.json", but some times it saves an extra '}' at the end of the file and i don't know why.

{"Alive":true,...,"Threads":20}}
pub fn write_config(data: &Struct_object) -> () {
    let file = OpenOptions::new().read(true).write(true).create(true).open("config.json");
    let mut refval: Struct_object = data.clone();

    match to_string::<Struct_object>(&mut refval) {
        Ok(u) => {
            match file {
                Ok(mut s) => match s.write(u.as_bytes()) {
                    Ok(_) => (),
                    Err(u) => warn!("Config.json couldn't be writen, data: {{ {} }}, Error: {{ {} }}", data, u),
                },
                Err(t) => {
                    warn!("Config.json couldn't be writen, data: {{ {} }}, Error: {{ {} }}", data, t);
                },
            }
        },
        Err(v) => warn!("Config.json couldn't be writen, data: {{ {} }}, Error: {{ {} }}", data, v),
    }


}
pub fn read_config() -> Struct_object{
    if file_exist() {
        let file = OpenOptions::new().read(true).open("config.json");
        let mut buf = String::new();

        match file {
            Ok(mut s) => {
                let _ = s.read_to_string(&mut buf);
                match from_str::<Struct_object>(&buf) {
                Ok(t) => t,
                Err(u) => {
                    warn!("config.json couldn't be loaded, loading default configuration, Error: {}", u);
                    Struct_object::default()
                }
            }
        },
            Err(v) => {warn!("config.json couldn't be readed, loading default configuration, Error: {}", v);
            Struct_object::default()},
        }
    } else {
        //write_config(&Struct_object::default());
        Struct_object::default()
    }

}

there is the code to read and write the data, and the loop is something like this:

pub fn daemon_variable_set(val: Struct_object) {
    loop {
        let data = read_config();
        val.write_rpc_url(data.read_rpc_url());
        thread::sleep(Duration::from_secs(1));
        write_config(&val);
        thread::sleep(Duration::from_secs(1));
        if !val.read_alive() {
            break;
        }
    }
    info!("Thread variable_set stop");
}

the information in the Struct_object are Arc<RwLock>, but in the serde is saving just the information of the primitive, and at read, i create the Arc to encapsulate the Primitives, so, i dont understand why is adding this extra '}' at the end of the line

Also i tried with the next, but was worst

use serde_json::de::from_reader;
use serde_json::ser::to_writer;

Upvotes: 1

Views: 257

Answers (2)

kmdreko
kmdreko

Reputation: 60012

You're overwriting the config.txt file but you aren't truncating it before writing to it, so data from previous writes can be seen if the data being written is shorter.

Before:

{"foo":12}

After writing {"foo":5} without truncating the file (since its 1 character shorter):

{"foo":5}}

You should simply use File::create:

Opens a file in write-only mode.

This function will create a file if it does not exist, and will truncate it if it does.

It will internally use .write(true).create(true).truncate(true) which is usually what you want when writing to a file like this.

Upvotes: 4

user2722968
user2722968

Reputation: 16475

You are missing a call to std::fs::OpenOptions::truncate(true) in your write_config() function.

Without that, the file will be written to, overwriting the previous content, but leaving the previous content in place. If the file's conent from the previous iteration of write_config happens to be longer by exactly one character (for instance: some value changes from 123 to 99), that will show up as an "extra" } during the next read.

Upvotes: 1

Related Questions