I'm trying to learn rust by writing a simple accounting program. I decided to store data as a json file locally. So the json file structure is like this:
{
"wallet": "wallet1",
"balance": 2000.0,
"transactions": [
{
"tr_type": "Withdraw",
"date": 20230522,
"volume": 300.0
},
{
"tr_type": "Deposit",
"date": 20230422,
"volume": 150.0
},
{
"tr_type": "Withdraw",
"date": 20230222,
"volume": 300.0
},
{
"tr_type": "Deposit",
"date": 20230707,
"volume": 200.0
}
]
}
In my program, I want to read this information from the file, do some calculations and show the results to the user. Also take new transaction input from user and add it to the json file. I came up with the code below (the user-input transaction is hardcoded as new_transaction):
use serde::{Deserialize, Serialize};
use std::fs::OpenOptions;
use std::io::prelude::*;
// use std::io::{BufWriter, Write};
#[derive(Serialize, Deserialize, Debug)]
struct Transaction {
tr_type: TRtype,
date: u64,
volume: f32,
}
#[derive(Serialize, Deserialize, Debug)]
struct Account {
wallet: String,
balance: f32,
transactions: Vec<Transaction>,
}
#[derive(Serialize, Deserialize, Debug)]
enum TRtype {
Deposit,
Withdraw,
}
fn main() -> std::io::Result<()> {
let mut myfile = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open("wallets.json")?;
let mut raw_json = String::new();
myfile.read_to_string(&mut raw_json)?;
let mut deserialized: Account = serde_json::from_str(&raw_json)?;
for trx in &deserialized.transactions {
println!(
"transaction: {:?}, volume = {}, date = {}",
trx.tr_type, trx.volume, trx.date
);
}
let new_transaction: Transaction = Transaction {
tr_type: TRtype::Deposit,
date: 20230707,
volume: 1500.0,
};
deserialized.transactions.push(new_transaction);
let serialized = serde_json::to_string(&deserialized).unwrap();
myfile.rewind().unwrap();
myfile.write_all(serialized.as_bytes())?;
Ok(())
}
This doesn't seem so elegant. For every new transaction the file will be overwritten completely.
So, is there a way to access the transaction array in the file and append to it without touching other lines?