JDK21升级后Discord Webhook发送JSON消息失败求助
JDK17升级到JDK21后Discord Webhook带Embed的JSON消息发送失败(错误码50109)
将Java版本从JDK17升级至JDK21后,Discord Webhook无法发送带Embed的JSON格式消息,但纯文本消息发送正常。报错提示请求体包含无效JSON(错误码50109),但生成的JSON经校验结构无误。以下是相关错误日志、消息构建代码及发送方法代码,需排查问题原因。
错误日志
Failed to send webhook. Response code: 400 Response: {"message": "The request body contains invalid JSON.", "code": 50109} Message: {"tts":false,"embeds":[{"color":0,"title":"Rare drop received!","type":"rich","fields":[]}],"content":"Rare drop received: message!"} Sent: {"tts":false,"embeds":[{"color":0,"title":"Rare drop received!","type":"rich","fields":[]}],"content":"Rare drop received: message!"} Got: {"message": "The request body contains invalid JSON.", "code": 50109}
消息构建代码
Message message = new Message(); Embed embedMessage = new Embed(); String mode = ""; switch (player.getGameMode()) { case IRONMAN: mode = "[Ironman] "; break; case HARDCORE_GROUP_IRONMAN: mode = "[Hardcore Group Ironman] "; break; case GROUP_IRONMAN: mode = "[Group Ironman] "; break; case HARDCORE_IRONMAN: mode = "[Hardcore Ironman] "; break; case ULTIMATE_IRONMAN: mode = "[Ultimate Ironman] "; break; } System.out.println("sendDiscordMessage3"); embedMessage.setTitle(mode + "Rare drop received!"); String npcdesc = npcDescriptiveName == null ? "" : " from " + npcDescriptiveName; embedMessage.setDescription(discordMessage + npcdesc + "!"); embedMessage.setColor(8917522); Thumbnail thumbnail = new Thumbnail(); thumbnail.setUrl("https://static.runelite.net/cache/item/icon/" + itemId + ".png"); embedMessage.setThumbnail(thumbnail); Footer footer = new Footer(); if(killcount == -1) footer.setText(""); else footer.setText(player.getDifficulty().Name + " mode" + " - KC: " + killcount + "."); embedMessage.setFooter(footer); System.out.println("Sending Discord message: " + message.toJson()); message.setEmbeds(embedMessage); message.setContent("Rare drop received: " + discordMessage + "!"); webhook.sendMessage(message.toJson());
消息发送方法代码
public void sendMessage(JSONObject message) { try { // Convert the JSON message to a string String messageString = message.toString(); // Create the HttpRequestWithBody object HttpRequestWithBody request = Unirest.post(url) .header("Content-Type", "application/json"); // Set the request body request.body(messageString); // Make the HTTP request HttpResponse<String> res = request.asString(); if (res.getStatus() == 200) { System.out.println("Webhook sent successfully."); } else { System.out.println("Failed to send webhook. Response code: " + res.getStatus()); System.out.println("Response: " + res.getBody()); System.out.println("Message: " + messageString); } if (verbose) { System.out.println("Sent: " + messageString); System.out.println("Got: " + res.getBody()); } } catch (UnirestException e) { ServerWrapper.logError("Failed to send webhook: " + message.toString(), e); } }
排查分析与解决方案
可能原因
- 空字段序列化异常:JDK21环境下,JSON序列化可能将空字符串字段(如footer的空text)转为
null,或保留无效空字段结构,触发Discord的JSON校验。 - JSON库兼容性问题:使用的JSON处理组件(如Unirest依赖的库)在JDK21下存在兼容bug,生成的JSON存在隐性语法错误(如转义、编码问题)。
- 请求编码不明确:JDK21默认HTTP编码变更,导致发送的JSON编码不符合Discord要求。
解决步骤
优化空字段处理:
- 打印
message.toJson()的完整输出,确认空值字段是否为Discord允许的格式(如空字符串而非null)。 - 修改Embed构建逻辑:当footer.text为空时,直接不设置footer字段,避免生成无效空结构。
- 打印
更换可靠的JSON序列化方式:
- 放弃
JSONObject.toString(),改用Jackson或Gson手动序列化,同时配置忽略空值字段:// Gson示例 Gson gson = new GsonBuilder().serializeNulls(false).create(); String messageString = gson.toJson(message);
- 放弃
明确请求编码:
- 在Unirest请求中指定UTF-8编码:
HttpRequestWithBody request = Unirest.post(url) .header("Content-Type", "application/json; charset=UTF-8");
- 在Unirest请求中指定UTF-8编码:
升级Unirest版本:
- 更换为支持JDK21的最新Unirest版本,解决旧版本与JDK21的兼容性问题。
内容的提问来源于stack exchange,提问作者Reprisal Gaming
相关产品推荐
相关产品推荐

