尝试发出命令来存储和撤回 json 文件中的信息

Trying to make a command to store and retreat info from a json file

我正在尝试创建一个命令来存储角色的名称、描述和图像,以及另一个命令来在嵌入中检索该数据,但我在使用 json 文件时遇到了问题

这是我添加它们的代码:

    @client.command()
    async def addskillset(ctx):
        await ctx.send("Let's add this skillset!")

        questions = ["What is the monster name?","What is the monster description?","what is the monster image link?"]

        answers = []

        #code checking the questions results

        embedkra = nextcord.Embed(title = f"{answers[0]}", description = f"{answers[1]}",color=ctx.author.color)
        embedkra.set_image(url = f"{answers[2]}")
        mess = await ctx.reply(embed=embedkra,mention_author=False)
        
        await mess.add_reaction('✅')
        await mess.add_reaction('❌')

        
        def check(reaction, user):
          return user == ctx.author and (str(reaction.emoji) == "✅" or "❌")
        try:
          reaction, user = await client.wait_for('reaction_add', timeout=1000.0, check=check)
        except asyncio.TimeoutError:
           #giving a message that the time is over
        else:
          if reaction.emoji == "✅":
            monsters = await get_skillsets_data() #this data is added at the end

            if str(monster_name) in monsters:
                await ctx.reply("the monster is already added")
            else:
                monsters[str(monster_name)]["monster_name"] = {}
                monsters[str(monster_name)]["monster_name"] = answers[0]
                monsters[str(monster_name)]["monster_description"] = answers[1]
                monsters[str(monster_name)]["monster_image"] = answers[2]

                with open('skillsets.json','w') as f:
                    json.dump(monsters,f)

                await mess.delete()
                await ctx.reply(f"{answers[0]} successfully added to the list")

获取包含询问信息的嵌入的代码:

            
    @client.command()
    async def skilltest(ctx,*,monster_name):
        data = open('skillsets.json').read()
        data = json.loads(data)
        if str(monster_name) in data:
          name = data["monster_name"]
          description = data["monster_description"]
          link = data["monster_image"]


          embedkra = nextcord.Embed(title = f"{name}", description = f"{description}",color=ctx.author.color)
          embedkra.set_image(url = f"{link}")
          await ctx.reply(embed=embedkra,mention_author=False)        

        else:
          # otherwise, it is still None meaning we didn't find it
          await ctx.reply("monster not found",mention_author=False)

我的 json 应该是这样的:

{"katufo": {"monster_name": "Katufo","Monster_description":"Katufo is the best","Monster_image":"#image_link"},
"armor claw":{"monster_name": "Armor Claw","Monster_description":"Armor claw is the best","Monster_image":#image_link}}

第一个命令中使用的get_skillsets_data:

async def get_skillsets_data():
    with open('skillsets.json','r') as f:
        monsters = json.load(f)

    return monsters

如果您的 json 看起来像上面显示的那样,

{
   "katufo":{
      "monster_name":"Katufo",
      "Monster_description":"Katufo is the best",
      "Monster_image":"#image_link"
   },
   "armor claw":{
      "monster_name":"Armor Claw",
      "Monster_description":"Armor claw is the best",
      "Monster_image":"#image_link"
   }
}

那就没有data["monster_name"]你的JSON里面的两个对象分别叫katufo和armor_claw。要获得其中之一,您只需编写 data['katufo']['monster_name']data.katufo.monster_name.

你的问题源于这样查找怪物名称:

 if str(monster_name) in data:
          name = data["monster_name"]
          description = data["monster_description"]
          link = data["monster_image"]

你可以做的是遍历数据,因为它包含几个怪物,然后在每个对象上,检查你所做的:

for monster in data:
    if str(monster_name) in monster.values():
        name = monster.monster_name
        description = monster.Monster_description
        link = monster.Monster_image

想一想,变量的命名方式不是我个人推荐的。不要害怕添加更长的描述性名称,这样代码中的内容对您来说更有意义。另外,在你提供的JSON中,有些属性以大写字母开头,你应该考虑一下。

编辑: python 中的字典等同于 Javascript 中的对象,并使用我们可以在下面看到的相同语法进行初始化:

monster_data = {}

但是既然你想要这些怪物的特定结构,我们可以更进一步,创建一个名为 add_monster_object():

的函数
def add_monster_object(original_dict, new_monster):
    
    new_monster = {
        "monster_name": '',
        "monster_description": '',
        "monster_image": '' 
    }

    #Now we have a new empty object with the correct names.
    
    return original_dict.update(new_monster)

现在,每次您 运行 这个具有给定名称的函数时,字典中都会有一个具有该名称的对象。例如,如果用户将 armor_sword 写为 monster_name 属性,那么我们可以将上面的函数调用为 add_monster_object(original_dict, monster_name)。 如果我们以您的初始口述为例,这将 return this:

{
   "katufo":{
      "monster_name":"Katufo",
      "Monster_description":"Katufo is the best",
      "Monster_image":"#image_link"
   },
   "armor claw":{
      "monster_name":"Armor Claw",
      "Monster_description":"Armor claw is the best",
      "Monster_image":"#image_link"
   },
   "armor sword":{
       "monster_name":"",
       "monster_description":"",
       "monster_image":""
   }
}

然后您可以根据需要填充它们,或更新函数以获取更多参数。这里的重要部分是您花一分钟时间弄清楚要保存的内容。然后确保您可以从文件中读取和写入,并且您应该有一个稍微简单的结构。 警告:这不是一劳永逸的方法,您还必须考虑特殊情况,例如添加一个已经存在的对象等等。

如果您决定使用 Replit,您可以使用他们的数据库来创建类似的功能,但您不必担心读取和写入文件。

就目前而言,我仍然认为您需要继续使用您的机器人,在下一个实际问题出现之前添加我提到的一些更改,因为有很多地方不太正确。我还建议您将所有内容分解为管理部分,1 是从文件中读取。 2 会写。 3 将字典写入文件。 4 更新字典等等。祝你好运!

好吧,当您尝试从 json 文件中检索数据时,现在尝试使用 name = data["katufo"]["monster_name"],它只会检索键 katufomonster_name。如果您想检索 armor claw 的数据,代码必须像这样 name = data["armor claw"]["monster_name"]。所以试试这个代码:

@client.command()
async def skilltest(ctx,*,monster):
    data = open('skillsets.json').read()
    data = json.loads(data)
    if str(monster) in data:
      name = data[f"monster"]["monster_name"]
      description = data[f"monster"]["Monster_description"]
      link = data[f"monster"]["Monster_image"]
      embedkra = nextcord.Embed(title = f"{name}", description = f"{description}",color=ctx.author.color)
      embedkra.set_image(url = f"{link}")
      await ctx.reply(embed=embedkra,mention_author=False)

    

     else:
      # otherwise, it is still None meaning we didn't find it
      await ctx.reply("monster not found",mention_author=False)

希望这对你有用:)