Skip to content
← Dist
rustjson_writer.rsrustserdejson

Generic JSON file writer

Serialize any Serialize value to a pretty JSON file with create/truncate semantics.

Generic over T: Serialize. Creates parent dirs, writes atomically-enough via a temp file + rename.

use std::{
    fs::{self, File},
    io::Write,
    path::Path,
};

use serde::Serialize;
use serde_json::to_vec_pretty;

pub fn write_json_file<T, P>(path: P, value: &T) -> std::io::Result<()>
where
    T: Serialize + ?Sized,
    P: AsRef<Path>,
{
    let path = path.as_ref();
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }

    let bytes = to_vec_pretty(value).map_err(|e| {
        std::io::Error::new(std::io::ErrorKind::InvalidData, e)
    })?;

    let tmp = path.with_extension("json.tmp");
    {
        let mut file = File::create(&tmp)?;
        file.write_all(&bytes)?;
        file.write_all(b"\n")?;
        file.sync_all()?;
    }
    fs::rename(&tmp, path)?;
    Ok(())
}

#[derive(Serialize)]
struct Config {
    name: String,
    retries: u32,
}

fn main() -> std::io::Result<()> {
    write_json_file(
        "out/config.json",
        &Config {
            name: "demo".into(),
            retries: 3,
        },
    )
}