从json字符串中提取变量

Posted

技术标签:

【中文标题】从json字符串中提取变量【英文标题】:Extract variables from json string 【发布时间】:2021-05-27 05:56:47 【问题描述】:

上下文:

我正在使用 discord.js 库和 MongoDB(使用 mongoose)制作一个 Discord 机器人。我创建了一个脚本,可以从存储在我的 MongoDB 数据库中的数据中构造消息。例如,如果我的 Discord 服务器上的用户键入“!hello”,它将查询我的数据库以构造一个回复,例如“Hello to you!”。

我将回复消息数据存储在这样的文档中:


    "command": "!hello",
    "content": "Hello to you!"

(我自愿省略了一些在我的问题上下文中无用的属性)

然后在我的代码中检索它,例如:

let retrievedReply;
await mongo().then(async mongoose => 
    try 
        let query = command: message.content;
        retrievedReply = await replySchema.findOne(query);
     finally 
        mongoose.connection.close();
    
);
message.reply(retrievedReply.content);

我的问题:

现在,假设我希望它响应“Hello 用户名!”。

如果我不使用来自 mongo 的数据构建我的回复,我可以简单地执行以下操作:

message.reply(`Hello $message.member.nickname!`);

message.reply("Hello " + message.member.nickname + "!");

因此,换句话说,使用 backticks$ 语法或(但我不喜欢它),拆分我的字符串并像第二个一样连接我的属性值例子。

问题是,我们不能以 json 格式(由 MongoDB 使用)将字符串存储在反引号内。所以即使我像这样构建我的文档:


    "command": "hello",
    "content": "Hello $message.member.nickname!"

$message.member.nickname 不会被解释为一个属性值,而是一个简单的字符串。

1000 美元的问题:

如何在我的代码中使用此属性?我考虑过使用正则表达式提取它,但它并没有改变它仍然是一个字符串的事实。有没有办法从字符串“转换”为可用变量?

编辑

自从 Brettski(正确地)问我以来,这是我想要的一个例子:

message.member.send(`Hello $message.member!`);

这里的 message.member 属性表示 Discord 公会的成员对象。它包含很多东西,比如它对公会的权限、它的角色等。 当我们在消息中使用成员对象时,Discord 会像下面这样提及该成员。

它与其他属性(例如频道)的工作方式相同。然后用户可以点击那些查看会员信息或直接进入频道等。我希望能够使用它。

【问题讨论】:

设置 message.member.nickname 等于一个变量并在你的字符串中使用它 @cbracketdash 嗯,感谢您的评论,但它不会改变任何东西。问题是我不能在我的字符串中使用变量。 this 有帮助吗? @0x435d2d 不,您的链接与我想要做的相反。他/她有一个带有变量的对象,他/她想将其转换为 json 格式。这不是我想要达到的目标。 如果在字符串中放入一个标记,然后用名称替换它会怎样?因此,您的内容可能类似于 "hello ~membernickname~!" 并在 message.reply 之前或之前对值进行替换。 【参考方案1】:

这是正确的,您将无法以 Mongo 或其他方式存储字符串文字。

虽然我必须在您的字符串中放置一个标记,然后在 message.reply() 或之前对其进行替换。

示例:

const helloCommand = 
  "command": "hello",
  "content": "Hello ~~membernickname~~!"
;

在本例中,要替换的令牌是 ~~membernickname~~

你可以用这样的东西来做替换:

const command = JSON.parse(helloCommand)
message.member.send(command.content.replace('~~membernickname~~', message.member));

发送到send() 命令的结果字符串是相同的。因此,如果昵称是@brettski,则字符串“Hello @brettski”将被发送到send() 命令。

在你的例子中:

message.reply(`Hello $message.member.nickname!`);

部分:

`Hello $message.member.nickname!`

是字符串文字 (template literals)。 message.reply() 函数最终得到的是 'Hello Nickname' 一个字符串。所以替换应该工作。作为测试,您可以将message.reply() 中使用的字符串硬编码为已知昵称,它应该会提供您期望的结果。

【讨论】:

是的,它可以工作,但它仍然是一个字符串。我希望它是可点击的。我没有很好地解释它,但是在 discord.js 中,如果我使用代表用户的变量,它将被 discord 客户端识别并写为提及,我们可以单击名称查看信息关于会员或频道等。 您需要将什么传回 Discord?你能举一个例子来说明它的期望吗?对 Discord.js api (discord.js.org) 中位置的引用也可能会有所帮助。 对不起,响应时间。我在最后一部分编辑了我的问题。 看到您正在发送messsage.reply() 一个字符串,我看不出使用替换不起作用的任何原因。您将使用包含在字符串中的昵称发送消息,与文字模板所做的没有什么不同。 因为如果我只是将其作为字符串发送,则名称或频道将无法点击,我希望它可以点击。 replace 方法当然很简单,但它只适用于字符串。【参考方案2】:

好吧,@Brettski 让我走上了正轨,因为我可以将用户或频道的 ID 直接用作消息中和特定标签之间的字符串。

要重用我的问题中的示例,我可以使用此语法来提及用户:

“”

我所做的是,如果我想在回复中提及命令的作者,我将文本放在我的 mongoDB 文档中:

const helloCommand = 
  "command": "hello",
  "content": "Hello $member$!"
;

然后,在我的代码中,我可以简单地使用:

message.reply((retrieveReply.content).replace(/\$member\$/g, `<@$message.member.id>`))

当然,我想使用更多属性,所以我做了一个类似的函数:

const messageContentReplace = function(content) 
    const replaceableStrings = 
                "$member$": `<@$message.member.id>`,
                "$memberName$": message.member.displayName,
                "$guild$": message.guild.name
    
    return content.replace(/(\$member\$)|(\$memberName\$)|(\$guild\$)/g, match => 
        return replaceableStrings[match];
);

(实际上,我做了一些更复杂的事情,因为我使用嵌入消息作为包含多个字段等的响应...请参阅 here 关于嵌入)

【讨论】:

以上是关于从json字符串中提取变量的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spark 从 DynamoDB JSON 字符串中提取嵌套的 Json 字段?

从 JSON 数组中的字符串中提取字段

PHP:如何从字符串转储中提取 JSON 字符串

从 powershell 中的 JSON 文件中提取子字符串

从 JSON 中提取很长的字符串到 CLOB

如何从 BigQuery 中的 JSON 字符串中提取数组