discord.py构造embed发送日志报Member不可JSON序列化错误
报错原因
discord.Embed.from_dict() 内部会对传入的字典做JSON序列化校验,要求字典内所有值都必须是可JSON序列化的原生类型(字符串、数字、布尔值、嵌套字典/列表等)。
你的代码中直接将discord.Member/discord.User类型的实例对象赋值给了embed字段的value属性:
{ 'name' : 'Name:', 'value' : target # 直接传入Member对象,不是原生可序列化类型 }, { 'name' : 'Moderator:', 'value' : mod # 直接传入Member对象,不是原生可序列化类型 }
Discord的成员对象不属于JSON可序列化的原生类型,因此触发TypeError: Object of type Member is not JSON serializable报错。
修复方案
- 将embed字典中直接传入的成员对象转为字符串类型的合法值:需要@用户就用
对象.mention,需要显示用户名+鉴别号就用str(对象),需要显示用户ID就用str(对象.id) - 补全原代码里的遗漏问题:给Reason字段补全默认inline属性、提前定义embed用的颜色值、增加target为空时的错误提示、将参数类型改为
discord.Member(discord.User是跨公会的用户抽象,没有加角色的权限)、给reason参数加*前缀以接收带空格的完整禁言理由
修复后的完整可运行代码:
import discord from discord import Embed from discord.ext import commands # 定义mod日志嵌入条的颜色,禁言操作可使用红色 MUTE_LOG_COLOR = 0xff0000 def log_embed(target : discord.Member, mod : discord.Member, action : str, reason : str = None): embed = { 'title' : f'{target.mention} has been {action}', 'type' : 'rich', 'color' : MUTE_LOG_COLOR, 'fields' : [ { 'name' : 'Name:', 'value' : str(target), # 转为「用户名#鉴别号」格式的字符串 'inline': True }, { 'name' : 'Moderator:', 'value' : str(mod), # 转为字符串 'inline': True }, { 'name' : 'Reason:', 'value' : reason.capitalize() if reason else 'No reason given', 'inline' : True } ] } return embed @bot.command() @commands.has_role('Staff') async def mute(ctx, target : discord.Member = None, *, reason : str = None): # 未指定禁言目标时返回提示 if not target: await ctx.send("请指定需要禁言的目标用户") return # 获取公会内的muted角色 muted_role = discord.utils.get(ctx.guild.roles, name='muted') await target.add_roles(muted_role, reason=reason) # 发送日志到mod-log频道 channel = discord.utils.get(ctx.guild.channels, name='mod-log') if channel: await channel.send(embed = Embed.from_dict(log_embed(target=target, mod=ctx.author, action='muted', reason=reason))) await ctx.send(f"已对 {target.mention} 完成禁言操作")
内容的提问来源于stack exchange,提问作者deadinside
相关产品推荐
相关产品推荐

