You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Salesforce APEX REST API问题:无法向@HttpPost函数传入JSON负载

问题排查:Salesforce APEX REST API JSON解析错误

我开发了一个APEX类实现RestResource,专门处理HTTP POST请求(REST API),用来创建平台事件。因为有number这类受保护关键字,所以选择手动解析传入的JSON负载。

测试时遇到异常:负载为空时,函数能正常进入try/catch逻辑;但负载包含字段时,会触发未捕获错误,错误信息如下:

{"message":"Unexpected parameter encountered during deserialization: message_id at [line:1, column:17]","errorCode":"JSON_PARSER_ERROR"}]'

测试用curl命令

curl -X POST -H "Authorization: Bearer xxxxxxxx" -H "Content-Type: application/json" -d '{
  "message_id": "12345",
  "mobileNumber": "1234567890",
  "text": "This is a test message",
  "sim_card_number": "SIM123",
  "reception_date": "2023-10-18 14:30:00"
}' "https://myinstanceoftest.sandbox.my.salesforce.com/services/apexrest/incomingTextMessages"

对应的APEX类代码

@RestResource(urlMapping='/incomingTextMessages/*')
global with sharing class AC14_IncomingTextMessage {

    // Define the JSON structure to match the incoming data.
    global class IncomingTextMessage {
        public String message_id;
        public String mobileNumber;
        public String text;
        public String sim_card_number;
        public String reception_date;
    }

    // Define the response structure.
    global class Response {
        public String status;
        public String message;
    }

    @HttpPost
    global static Response createIncomingTextMessage(String jsonPayload) {
        System.debug('Received JSON Message: ' + jsonPayload);
        
        Response response = new Response();
        
        try {

            Map<String, Object> jsonMap = (Map<String, Object>) JSON.deserializeUntyped(jsonPayload);
            
            // Create an instance of the IncomingTextMessage class and manually map the field "number" to "mobileNumber."
            IncomingTextMessage incomingMessage = new IncomingTextMessage();
            incomingMessage.message_id = (String) jsonMap.get('message_id');
            incomingMessage.mobileNumber = (String) jsonMap.get('number');
            incomingMessage.text = (String) jsonMap.get('text');
            incomingMessage.sim_card_number = (String) jsonMap.get('sim_card_number');
            incomingMessage.reception_date = (String) jsonMap.get('reception_date');

            // Create a new Platform Event and set its fields.
            IncomingTextMessage__e newEvent = new IncomingTextMessage__e(
                Message_Id__c = incomingMessage.message_id,
                mobileNumber__c = incomingMessage.mobileNumber,
                Text__c = incomingMessage.text,
                Sim_Card_Number__c = incomingMessage.sim_card_number,
                Reception_Date__c = DateTime.valueOf(incomingMessage.reception_date)
            );

            // Publish the Platform Event.
            EventBus.publish(newEvent);

            response.status = 'Success';
            response.message = 'Platform Event created successfully';
        } catch (Exception e) {
            response.status = 'Error';
            response.message = 'Error processing the request: ' + e.getMessage();
        }
                
        return response;
    }
}

问题根源

你的APEX方法定义了String jsonPayload作为参数,Salesforce会自动尝试将POST请求的JSON负载反序列化为这个参数对应的结构。但当你传入包含message_id等字段的JSON对象时,Salesforce无法将整个JSON对象映射到单个字符串参数,因此触发了JSON解析错误。

修复方案

直接通过RestContext.request.requestBody获取原始请求体,再手动解析,避免Salesforce自动反序列化参数。修改后的代码如下:

@RestResource(urlMapping='/incomingTextMessages/*')
global with sharing class AC14_IncomingTextMessage {

    // 定义响应结构
    global class Response {
        public String status;
        public String message;
    }

    @HttpPost
    global static Response createIncomingTextMessage() {
        // 直接获取请求体内容
        String jsonPayload = RestContext.request.requestBody.toString();
        System.debug('Received JSON Message: ' + jsonPayload);
        
        Response response = new Response();
        
        try {
            Map<String, Object> jsonMap = (Map<String, Object>) JSON.deserializeUntyped(jsonPayload);
            
            // 手动映射字段,注意与curl请求的字段名匹配
            String message_id = (String) jsonMap.get('message_id');
            String mobileNumber = (String) jsonMap.get('mobileNumber');
            String text = (String) jsonMap.get('text');
            String sim_card_number = (String) jsonMap.get('sim_card_number');
            String reception_date = (String) jsonMap.get('reception_date');

            // 创建平台事件
            IncomingTextMessage__e newEvent = new IncomingTextMessage__e(
                Message_Id__c = message_id,
                mobileNumber__c = mobileNumber,
                Text__c = text,
                Sim_Card_Number__c = sim_card_number,
                Reception_Date__c = DateTime.valueOf(reception_date)
            );

            // 发布事件
            EventBus.publish(newEvent);

            response.status = 'Success';
            response.message = '平台事件创建成功';
        } catch (Exception e) {
            response.status = 'Error';
            response.message = '处理请求时出错: ' + e.getMessage();
        }
                
        return response;
    }
}

额外注意事项

  • 原代码中incomingMessage.mobileNumber = (String) jsonMap.get('number');与curl请求的字段mobileNumber不匹配,修正后才能正确获取手机号数据。
  • 移除了无用的IncomingTextMessage内部类,因为已经手动解析JSON,无需该类做结构映射。

内容的提问来源于stack exchange,提问作者Nicolas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 14:10:38