首页 > 解决方案 > 如何使用 fs 向我的 JSON 文件添加更多值?

问题描述

我正在制作一个Discord 机器人,我想添加这样的 JSON 值

{
    "Server ID": {
        "01-Ticket": {
            User: "Some ID",
            Channel_ID: "Some ID"
        }
    }
}

我使用添加了一个,fs但是当我添加另一个时,它会删除第一个值 ( "01-Ticket")

这是我的index.js

channel.send(welcomeEmbed).then(async msg => {
     await msg.react("")
     let tickets = require('./tickets.json')[msg.guild.id];
     tickets[msg.guild.id]
     console.log(tickets)
     fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 5))
})

标签: javascriptnode.jsdiscord.js

解决方案


There are simply two things you need to do: create a new name for the ticket (if the previous one was "01-Ticket", then you need to name the new one "02-Ticket") and insert the ticket into the object using its new name.

A Solution

Here's a full example of how you could do such a thing:

let tickets = require('./tickets.json');
let newName = "01-Ticket";

if (msg.guild.id in tickets) {
    let guildTickets = tickets[msg.guild.id];

    let oldName = Object.keys(guildTickets).sort((a,b) => a.localeCompare(b)).pop();
    let newNumber = Number(oldName.split("-")[0]) + 1;
    let length = newNumber.toString().length;
    newName = ("0" + newNumber).slice(-((length - 1) + Math.ceil(2 / length))) + "-Ticket";
}
else {
    tickets[msg.guild.id] = {};
}

let ticket = {
    User: msg.author.id,
    Channel_ID: msg.channel.id
}

tickets[msg.guild.id][newName] = ticket;

fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 5))

Explanation

And below is the same code, but I've commented each new line to make it easier for you to understand the purpose of everything I am doing in this example:

let tickets = require('./tickets.json');
let newName = "01-Ticket";

//Check if the guild has any tickets
if (msg.guild.id in tickets) {
    //The guild does already have tickets

    //Get the tickets for this guild
    let guildTickets = tickets[msg.guild.id];

    //Take all of the ticket names ("01-Ticket", "02-Ticket", etc.) via Object.keys(),
    //sort them in ascending numerical order via .sort(),
    //and get the last one (the largest number, or the name of the latest ticket) via .pop()
    let oldName = Object.keys(guildTickets).sort((a,b) => a.localeCompare(b)).pop();

    //Take the old ticket's name ("01-Ticket"), get its number ("01"), and increment
    //it by one (so now it would be "2")
    let newNumber = Number(oldName.split("-")[0]) + 1;

    //The length of the new number (for "2", the length would be 1)
    let length = newNumber.toString().length;

    //Now add a single "0" to the start of the name (name so far: "0")
    //then add the new number (name so far: "02")
    //Then, from the end of the name go back as far as necessary to get the proper name (name so far: "02")
    //This works with all amounts of digits (ex: 2 -> "02"; 12 -> "12")
    newName = ("0" + newNumber).slice(-((length - 1) + Math.ceil(2 / length))) + "-Ticket";
}
else {
    //No tickets have been made in this guild yet

    //So set the guild's ticket list to an empty object
    tickets[msg.guild.id] = {};
}

//Create the new ticket to add to the guild's ticket list
let ticket = {
    User: msg.author.id,
    Channel_ID: msg.channel.id
}

//Add the ticket to the guild's ticket list
tickets[msg.guild.id][newName] = ticket;

//Update the tickets.json with your updated 'tickets' object
fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 5))

So first I am checking whether or not the guild's ID is already in tickets.json. If it isn't, we are adding it in as an empty object (and we add in the new ticket with the default name: "01-Ticket"). If the guild's ID is already in the file, then we need to create a new name for our new ticket. So first I get the object representing the guild's tickets. Then I get all of the keys in that object (which are the tickets' names: "01-Ticket", "02-Ticket", and so on). I sort those keys from least to greatest (since all of the ticket names begin with numbers, this is essentially sorting them numerically), and retrieve the last ticket name in the sorted list using .pop() (which is the ticket name starting with the largest number). I then take the number from that ticket name, and add one to it. Then I make sure to add a "0" at the beginning of the new ticket name if it is only one digit long; I am using a complex formula and .slice() to do so, but you could do this with a simple if statement. I then create the ticket itself, setting its user ID and channel ID properties. Finally, I add the ticket to the guild's ticket list by updating the tickets variable, and then update tickets.json with the new value of tickets.

The new name creation in this code is tested and works. The rest of the code is not tested, but works exactly the same as it does in some of my own bots' working code. If any part of this answer doesn't make sense or if you spot an error, feel free to comment it.


推荐阅读