从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 字段?