My JSON files keeps breaking when writing for some reason

Ok so then, my databases are already in JSON. What package should I then use to write into the JSON?
- I want JSON, not SQLite or any other database type.

By JSON I assume you mean the resulting storage file to be a text file containing JSON?

NeDB example https://glitch.com/~ne-db

Produces a file …

$ cat .data/datafile 
{"firstName":"John","lastName":"Hancock","_id":"EI5tpoIW0aQarHkl"}
{"firstName":"Liz","lastName":"Smith","_id":"EIkyZdTkwri9jyYX"}
{"firstName":"Ahmed","lastName":"Khan","_id":"VscETz0r3ns7Bhwo"}
{"firstName":"jupiter","lastName":"rolls","_id":"TvVK5YneXVqOJCZb"}

Its not quite JSON, its a newline-separated list of JSON lines.


low-db example https://glitch.com/~low-db

Produces a JSON storage file …

$ cat .data/db.json 
{
  "users": [
    {
      "firstName": "John",
      "lastName": "Hancock"
    },
    {
      "firstName": "Liz",
      "lastName": "Smith"
    },
    {
      "firstName": "Ahmed",
      "lastName": "Khan"
    },
    {
      "firstName": "silver",
      "lastName": "tongue"
    }
  ]
}

By JSON, I literally mean JSON.
Like this

{
  "server": {
    "bans": {},
    "mutes": {},
    "kicks": {},
    "warns": {},
    "configs": {
      "punishLogs": "false",
      "punishLogchannel": "",
      "actionLogs": "false",
      "actionsLogsChannel": "",
      "appLogs": "false",
      "appLogsChannel": "",
      "xprate": "1",
      "levelRewards": {},
      "levelMsgs": "true",
      "levelChannel": "630773383398948875",
      "levelMsg": "Congrats {member}! Your level({level}) is higher than Apex's happiness!",
      "premium": "true"
    },
    "levels": {
      "266162824529707008": {
        "level": 4,
        "xp": 1138
      },
      "591012981165522945": {
        "level": 3,
        "xp": 693
      }
    }
  }
}

Any of the databases can handle that: quickdb, nedb, lowdb

Taking the last example, low-db https://github.com/typicode/lowdb#usage …

// Set some defaults (required if your JSON file is empty)
db.defaults({ posts: [], user: {}, count: 0 })
  .write()

// Add a post
db.get('posts')
  .push({ id: 1, title: 'lowdb is awesome'})
  .write()

// Set a user using Lodash shorthand syntax
db.set('user.name', 'typicode')
  .write()
  
// Increment count
db.update('count', n => n + 1)
  .write()

Its a simple transformation to your own structure.

I recommend sleeping on the decision :sleeping:

Alright, I’ma get some sleep now.
Though, one last question for now, how would I get example the punishLogs from inside of configs inside of server inside of the file?

Taking lowdb again …

db.get('server.configs.punishLogs')
  .value()

The other databases have similar functionality with different syntax.

Edit - note that using a database doesn’t do away with all concurrency issues.

It makes things a lot easier for most cases where a different piece of data is being read and altered.

Where the same piece of data is being changed in one command and in another command, the timing may mean the “most recent write wins”.

Usually this is okay, and if its not okay, the item is split into a list instead, to allow for multiple entries.

There’s another approach that might fit your project – all reads and writes to the in-memory object, and catch the process ending as a chance to write to an external file, if the cache is flagged as dirty (writes made).

Some downsides including no up-to-date access outside the current Node process, apart from that exposed in your APIs (webhooks/request handlers).

I still think a database is the best option!

When looking at lowdb’s docs, I can’t seem to find out how to edit the objects.
I am not used to database packages, so it’s a bit hard for me to understand them at first.
How would I edit ./databases/${message.guild.id}.json > server.configs.punishLogs to true?

Ok so, I managed to fix the issue by putting

if (message.content.startsWith('%')) return;

into my Leveling System, so that way it will not edit the database when I use %config.

Thank you for your help. I actually wouldn’t have realized this could fix it without you telling me this,

1 Like

Earlier I missed seeing the guild id at the top level … something like

db.defaults({ guilds: [] })
  .write()

db.get('guilds')
  .push({'id': message.guild.id})
  .write()
 
db.get('guilds')
  .find({id: message.guild.id})
  .set('server.configs.punishLogs', true)
  .write()

Results in

{
  "guilds": [
    {
      "id": "abcguildid",
      "server": {
        "configs": {
          "punishLogs": true
        }
      }
    }
  ]
}

Nice that you have a further insight :slight_smile:

2 Likes