serde_rw 1.0.2

Extend serde serializers and deserializers with the ability to read / write different file formats from / to files
Documentation
use std::fs::{read_to_string, write};
use std::io::Write;
use std::path::Path;

use serde::{Deserialize, Serialize};

/// Allow deserialization from JSON.
#[allow(clippy::module_name_repetitions)]
pub trait FromJson: for<'de> Deserialize<'de> {
    /// Deserializes an object from a JSON file.
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the deserialization fails.
    ///
    /// # Examples
    /// ```
    /// use serde_rw::FromJson;
    /// use serde::Deserialize;
    ///
    /// #[derive(Debug, Deserialize, Eq, PartialEq)]
    /// struct Person {
    ///     id: u32,
    ///     name: String,
    /// }
    ///
    /// #[cfg(feature = "json")]
    /// {
    ///     assert_eq!(
    ///         Person::from_json_file("./tests/person.json").unwrap(),
    ///         Person {
    ///             id: 1337,
    ///             name: "John Doe".to_string(),
    ///         }
    ///     );
    /// }
    /// ```
    fn from_json_file(filename: impl AsRef<Path>) -> crate::Result<Self> {
        <Self as FromJson>::from_json_string(&read_to_string(filename)?)
    }

    /// Deserializes an object from a JSON string.
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the deserialization fails.
    ///
    /// # Examples
    /// ```
    /// use serde_rw::FromJson;
    /// use serde::Deserialize;
    ///
    /// #[derive(Debug, Deserialize, Eq, PartialEq)]
    /// struct Person {
    ///     id: u32,
    ///     name: String,
    /// }
    ///
    /// const JSON: &str = r#"{"id": 1337, "name": "John Doe"}"#;
    ///
    /// #[cfg(feature = "json")]
    /// {
    ///     assert_eq!(
    ///         Person::from_json_string(JSON).unwrap(),
    ///         Person {
    ///             id: 1337,
    ///             name: "John Doe".to_string(),
    ///         }
    ///     );
    /// }
    /// ```
    fn from_json_string(text: &str) -> crate::Result<Self> {
        Ok(serde_json::from_str(text)?)
    }
}

/// Allow serialization to JSON.
#[allow(clippy::module_name_repetitions)]
pub trait ToJson: Serialize {
    /// Write object as JSON to a [writer](Write).
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the serialization fails.
    fn write_json<W>(&self, writer: W) -> crate::Result<()>
    where
        W: Write,
    {
        Ok(serde_json::to_writer(writer, self)?)
    }

    /// Write object as pretty JSON to a [writer](Write).
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the serialization fails.
    fn write_json_pretty<W>(&self, writer: W) -> crate::Result<()>
    where
        W: Write,
    {
        Ok(serde_json::to_writer_pretty(writer, self)?)
    }

    /// Return object as serialized JSON string.
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the serialization fails.
    fn to_json(&self) -> crate::Result<String> {
        Ok(serde_json::to_string(self)?)
    }

    /// Return object as prettified JSON string.
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the serialization fails.
    fn to_json_pretty(&self) -> crate::Result<String> {
        Ok(serde_json::to_string_pretty(self)?)
    }

    /// Write object as serialized JSON string to a file.
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the serialization fails.
    fn write_to_json_file(&self, filename: impl AsRef<Path>) -> crate::Result<()> {
        Ok(write(filename, <Self as ToJson>::to_json(self)?)?)
    }

    /// Write object as serialized JSON string to a file.
    ///
    /// # Errors
    ///
    /// Returns an [`Error`](crate::Error) if the serialization fails.
    fn write_to_json_file_pretty(&self, filename: impl AsRef<Path>) -> crate::Result<()> {
        Ok(write(filename, <Self as ToJson>::to_json_pretty(self)?)?)
    }
}