24 releases
0.1.23 | Jan 15, 2025 |
---|---|
0.1.22 | Dec 19, 2024 |
0.1.20 | Aug 29, 2024 |
#523 in Encoding
142 downloads per month
23KB
260 lines
struct-to-json-db
struct-to-json-db is a minimalist, file-based database tailored for straightforward Rust applications. Leveraging the power of the Serde crate, it effortlessly serializes and deserializes structured data stored as JSON files. This ensures simplicity, flexibility, and ease of integration for developers seeking a lightweight database solution without the overhead of setting up complex systems.
Table of Contents
Features
- Automatic ID Generation: Automatically generate unique identifiers for your structs.
- Serialization & Deserialization: Seamlessly convert structs to and from JSON files.
- Singleton Support: Manage singleton configurations effortlessly.
- Unique Keys: Enforce uniqueness on specified fields to maintain data integrity.
- Big Size Handling: Split large datasets into multiple JSON files for efficient data management.
- Data Encryption: Protect sensitive data using environment-based encryption keys.
- Relationship Management: Define and manage relationships between different data structs.
Example Code
For a practical example, visit the example code repository.
Getting Started
Installation
To integrate struct-to-json-db into your project, add it to your Cargo.toml
:
[dependencies]
struct-to-json-db = "x.x.x" # Replace x.x.x with the latest version
Alternatively, you can specify the GitHub repository directly:
[dependencies]
struct-to-json-db = { git = "https://github.com/acscoder/struct-to-json-db.git" }
Note: Always check crates.io for the latest version.
Configuration
Before using the database, configure the directory where your JSON files will be stored:
use struct_to_json_db::set_struct_json_path;
fn main() {
set_struct_json_path("./db/"); // Ensure the path ends with a slash (/)
}
Important: The path must end with a slash (
/
). For example,./db/
is correct, whereas./db
is incorrect.
Usage
Adding the Macro to Your Struct
Use the #[auto_json_db]
attribute macro to automatically add functionalities such as unique ID generation and data management methods to your structs.
Basic Usage
use struct_to_json_db::auto_json_db;
use serde::{Deserialize, Serialize};
#[auto_json_db]
#[derive(Serialize, Deserialize, Debug)]
struct YourStruct {
// Your fields here
}
With Unique Key
Enforce uniqueness on specific fields by specifying the unique
attribute:
use struct_to_json_db::auto_json_db;
use serde::{Deserialize, Serialize};
#[auto_json_db(unique = "your_unique_key")]
#[derive(Serialize, Deserialize, Debug)]
struct YourStruct {
// Your fields here
}
Handling Large Structs
For structs with large datasets, use the bigsize
attribute to split data into multiple files, enhancing performance and manageability:
use struct_to_json_db::auto_json_db;
use serde::{Deserialize, Serialize};
#[auto_json_db(bigsize, unique = "your_unique_key")]
#[derive(Serialize, Deserialize, Debug)]
struct YourStruct {
// Your fields here
}
Singleton Structs
Manage singleton configurations using the singleton
attribute:
use struct_to_json_db::auto_json_db;
use serde::{Deserialize, Serialize};
#[auto_json_db(singleton)]
#[derive(Serialize, Deserialize, Debug)]
struct Config {
// Configuration fields
}
Defining Relationships
Establish relationships between different structs using the json_db_relation!
macro. This facilitates relational data management, akin to foreign keys in traditional databases.
use struct_to_json_db::json_db_relation;
// Example: One Post has many Categories
json_db_relation!(Post = categories, Category);
// Example: One-to-One Relationship
json_db_relation!(Post = categories, Category, "1-1");
Encryption Support
Protect sensitive data by encrypting JSON files. Define an environment variable as your encryption key and specify it in the macro:
-
Set Up Environment Variable:
Create a
.env
file in your project root:APP_SECRET_KEY=your_secret_key
-
Load Environment Variables:
Use the
dotenv
crate to load the.env
file:use dotenv::dotenv; fn main() { dotenv().ok(); // Your code here }
-
Apply Encryption in Macro:
use struct_to_json_db::auto_json_db; use serde::{Deserialize, Serialize}; use dotenv::dotenv; #[auto_json_db(encript = "APP_SECRET_KEY")] #[derive(Serialize, Deserialize, Debug)] struct SensitiveData { // Sensitive fields }
Note: The
encript
attribute requires the specified environment variable (APP_SECRET_KEY
in this case) to be set. It uses this key to encrypt and decrypt your JSON data.
API Overview
The #[auto_json_db]
macro enriches your structs with a suite of methods to facilitate data management:
- Unique ID (
idx
): Automatically adds a unique identifier (u64
orString
) to the struct. - Constructor (
new
): Creates new instances of the struct. - CRUD Operations:
get_all()
: Retrieves all saved instances as aHashMap<idx, Struct>
.save()
: Saves a single instance to the JSON file.save_vec(v: Vec<Struct>)
: Saves multiple instances at once.get_by_id(id: idx)
: Fetches an instance by its unique ID.remove_by_id(id: idx)
: Removes an instance by its unique ID.clear()
: Deletes all instances from the JSON file.
- Relationship Methods: Manage relations between different structs as defined by
json_db_relation!
. - Encryption Handling:
set_data_string(file_path, db_string)
: Encrypts and writes data if encryption is enabled.get_data_string(file_path)
: Decrypts and reads data if encryption is enabled.
Example
Below is a comprehensive example demonstrating the usage of struct-to-json-db with encryption, unique keys, big size handling, and relationships.
use struct_to_json_db::*;
use serde::{Deserialize, Serialize};
use dotenv::dotenv;
#[auto_json_db(singleton, encript = "APP_SECRET_KEY")]
#[derive(Serialize, Deserialize, Debug)]
struct SiteConfig {
url: String,
limit: i32,
}
impl SiteConfig {
fn default() -> Self {
Self::new("".to_owned(), 0)
}
}
#[auto_json_db(bigsize, unique = "title")]
#[derive(Serialize, Deserialize, Debug)]
struct Post {
title: String,
description: String,
categories: Vec<u64>,
}
#[auto_json_db(unique = "name")]
#[derive(Serialize, Deserialize, Debug)]
struct Category {
name: String,
}
json_db_relation!(Post = categories, Category);
fn main() {
// Load environment variables from .env file
dotenv().ok();
// Set the directory for JSON database files
set_struct_json_path("./db/");
// Load the singleton SiteConfig
let mut config = SiteConfig::load();
println!("Site Config: {:?}", config);
// Retrieve all posts
let all_posts = Post::get_all();
println!("Number of posts: {}", all_posts.len());
// Create and save categories
let category1 = Category::new("Technology".to_owned());
let category2 = Category::new("Health".to_owned());
category1.save();
category2.save();
// Add a new post with assigned categories
let post_id = add_post(
"Rust Programming".to_owned(),
"An introduction to Rust.".to_owned(),
&vec![category1, category2],
);
println!("New Post ID: {:?}", post_id);
}
fn add_post(title: String, description: String, categories: &Vec<Category>) -> Option<u64> {
let mut post = Post::new(title, description, vec![]);
if !categories.is_empty() {
post.set_categories(categories);
}
post.save()
}
Explanation
-
SiteConfig Struct:
- Marked as a singleton with encryption enabled.
- Automatically loads and saves the configuration to
./db/SiteConfig.json
.
-
Post Struct:
- Configured with
bigsize
to handle large datasets by splitting into multiple files. - Enforces uniqueness on the
title
field.
- Configured with
-
Category Struct:
- Enforces uniqueness on the
name
field.
- Enforces uniqueness on the
-
Relationships:
- Defined a one-to-many relationship where a
Post
can have multipleCategories
.
- Defined a one-to-many relationship where a
-
Main Function:
- Initializes environment variables and sets the database path.
- Loads the singleton configuration.
- Retrieves and prints the number of posts.
- Creates and saves new categories.
- Adds a new post associated with the created categories.
Contributing
Contributions are highly encouraged! Whether it's reporting bugs, suggesting features, or submitting pull requests, your input helps make struct-to-json-db better for everyone.
-
Fork the Repository: Click the Fork button at the top right of the repository page.
-
Clone Your Fork:
git clone https://github.com/your-username/struct-to-json-db.git cd struct-to-json-db
-
Create a Feature Branch:
git checkout -b feature/your-feature-name
-
Commit Your Changes:
git commit -m "Add your message here"
-
Push to Your Fork:
git push origin feature/your-feature-name
-
Create a Pull Request: Navigate to your fork on GitHub, switch to your feature branch, and click the New Pull Request button.
License
This project is licensed under the Apache License 2.0. You are free to use, modify, and distribute this software as per the terms of the license.
Happy Coding! 🚀
Dependencies
~4–5.5MB
~104K SLoC