MT5通过WebRequest发送JSON至Discord报错400(无效JSON)求助
解决MT5通过Discord Webhook发送持仓信息的JSON无效问题
问题描述
运行MT5的MQL5代码获取持仓并通过Discord Webhook发送通知时,返回HTTP 400错误,提示请求体包含无效JSON。原代码及运行日志如下:
原代码
input string WebhookURL = "https://discord.com/api/webhooks/1288029176930242621/t-npSVLA5x8hv2QqAI8KfXbsiAXAtBMQcYyZyuuSYeFBOzr-AT-ldGGPAIXwUgeMOfB0"; void SendDiscordMessage(string message) { Print("Raw message: ", message); // Escape newlines in the message StringReplace(message, "\n", "\\n"); string json = "{\"content\":\"" + message + "\"}"; Print("Final JSON Payload: ", json); char data[]; StringToCharArray(json, data); ArrayResize(data, StringLen(json) + 1); // Ensure the array has enough space char result[]; string headers = "Content-Type: application/json"; Print("Sending with headers: ", headers); string result_headers; int res = WebRequest("POST", WebhookURL, headers, 5000, data, result, result_headers); if (res < 0) { Print("Error sending message: ", GetLastError()); return; } string response = CharArrayToString(result); Print("HTTP Response Code: ", res); Print("Response Raw Output: ", response); } void OnStart() { Print("Discord notification script running on MT5..."); int totalPositions = PositionsTotal(); Print("Total open positions: ", totalPositions); for (int i = 0; i < totalPositions; i++) { ulong ticket = PositionGetTicket(i); if (PositionSelectByTicket(ticket)) { string symbol = PositionGetString(POSITION_SYMBOL); double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN); double stopLoss = PositionGetDouble(POSITION_SL); double takeProfit = PositionGetDouble(POSITION_TP); // Format the message string message = StringFormat("New Trade: %s\\nEntry: %.2f\\nSL: %.2f\\nTP: %.2f", symbol, entryPrice, stopLoss, takeProfit); Print("Complete message: ", message); // Log the complete message SendDiscordMessage(message); } else { Print("Failed to select position with ticket: ", ticket); } } }
运行日志
2024.09.24 18:03:05.733 TelegeramALert (MESZ24,H1) Discord notification script running on MT5... 2024.09.24 18:03:05.733 TelegeramALert (MESZ24,H1) Total open positions: 1 2024.09.24 18:03:05.733 TelegeramALert (MESZ24,H1) Complete message: New Trade: MYMZ24\nEntry: 42574.00\nSL: 0.00\nTP: 0.00 2024.09.24 18:03:05.733 TelegeramALert (MESZ24,H1) Raw message: New Trade: MYMZ24\nEntry: 42574.00\nSL: 0.00\nTP: 0.00 2024.09.24 18:03:05.733 TelegeramALert (MESZ24,H1) Final JSON Payload: {"content":"New Trade: MYMZ24\nEntry: 42574.00\nSL: 0.00\nTP: 0.00"} 2024.09.24 18:03:05.733 TelegeramALert (MESZ24,H1) Sending with headers: Content-Type: application/json 2024.09.24 18:03:06.211 TelegeramALert (MESZ24,H1) HTTP Response Code: 400 2024.09.24 18:03:06.211 TelegeramALert (MESZ24,H1) Response Raw Output: {"message": "The request body contains invalid JSON.", "code": 50109}
问题原因
- 未转义的控制字符:代码生成的消息包含实际换行符(ASCII 10),而非JSON要求的转义序列
\\n,JSON规范禁止字符串内出现未转义的控制字符。 - 编码不匹配:MQL5默认用ANSI编码转换字符串,但Discord Webhook要求UTF-8编码的请求体,编码错误导致JSON解析失败。
修复后的代码
input string WebhookURL = "https://discord.com/api/webhooks/1288029176930242621/t-npSVLA5x8hv2QqAI8KfXbsiAXAtBMQcYyZyuuSYeFBOzr-AT-ldGGPAIXwUgeMOfB0"; void SendDiscordMessage(string message) { Print("Raw message: ", message); // 将实际换行符替换为JSON兼容的转义序列 StringReplace(message, "\n", "\\n"); // 转义消息中的双引号,避免破坏JSON结构 StringReplace(message, "\"", "\\\""); string json = "{\"content\":\"" + message + "\"}"; Print("Final JSON Payload: ", json); char data[]; // 使用UTF-8编码转换字符串,符合Discord要求 StringToCharArray(json, data, 0, StringLen(json), CP_UTF8); char result[]; string headers = "Content-Type: application/json; charset=utf-8"; Print("Sending with headers: ", headers); string result_headers; int res = WebRequest("POST", WebhookURL, headers, 5000, data, result, result_headers); if (res < 0) { Print("Error sending message: ", GetLastError()); return; } string response = CharArrayToString(result, 0, ArraySize(result), CP_UTF8); Print("HTTP Response Code: ", res); Print("Response Raw Output: ", response); } void OnStart() { Print("Discord notification script running on MT5..."); int totalPositions = PositionsTotal(); Print("Total open positions: ", totalPositions); for (int i = 0; i < totalPositions; i++) { ulong ticket = PositionGetTicket(i); if (PositionSelectByTicket(ticket)) { string symbol = PositionGetString(POSITION_SYMBOL); double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN); double stopLoss = PositionGetDouble(POSITION_SL); double takeProfit = PositionGetDouble(POSITION_TP); // 生成消息时直接使用转义的换行符 string message = StringFormat("New Trade: %s\\nEntry: %.2f\\nSL: %.2f\\nTP: %.2f", symbol, entryPrice, stopLoss, takeProfit); Print("Complete message: ", message); SendDiscordMessage(message); } else { Print("Failed to select position with ticket: ", ticket); } } }
关键改动说明
- 增强转义处理:新增双引号转义逻辑,避免持仓符号或内容含双引号时破坏JSON结构。
- UTF-8编码支持:字符串与字符数组的转换均指定
CP_UTF8参数,确保请求体编码符合Discord要求。 - 请求头优化:在
Content-Type中明确标注charset=utf-8,告知服务端请求体编码格式。 - 移除冗余操作:删除不必要的
ArrayResize,StringToCharArray会自动分配正确的数组空间。
内容的提问来源于stack exchange,提问作者yohans shegaw
相关产品推荐
相关产品推荐

