Salesforce APEX REST API:无法向 @httppost 函数提供 json 有效负载

问题描述 投票:0回答:2

我开发了一个 APEX 类来创建 RestResource,特别是一种处理 HTTP POST 请求(API REST)的方法。 该功能创建一个事件平台。 它需要一个 JSON 有效负载并解析它(手动,因为有一些受保护的关键字,例如“number”

当我执行curl命令来测试它时,它失败了(如果有效负载为空,则成功启动并运行该函数,但是当有效负载包含字段时,我得到了一个似乎无法通过try/catch结构捕获的错误)

你能帮忙吗?

这是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"

并收到此错误:

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

和 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;
    }
}

我尝试了几次curl测试,显示空负载工作正常(我的意思是,它失败了,但通过try/catch结构捕获) 我还开发了正在运行的测试类。

rest salesforce http-post apex
2个回答
0
投票

根据我对 POST 你的记忆:

  1. 不必费心向方法传递任何参数
  2. 稍微调整一下 JSON

https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_restrequest.htm

如果 Apex 方法没有参数,则 Apex REST 复制 HTTP 请求正文放入 RestRequest.requestBody 属性中。如果有 参数,然后 Apex REST 尝试将数据反序列化为这些 参数和数据不会被反序列化到 RestRequest.requestBody 属性。

对于1来说,你的想法是你可以从中阅读你需要的一切

RestRequest req = RestContext.request;
System.debug(req.requestURI);
System.debug(req.requestBody);

好吧...如果您希望在另一个非 API 上下文中重用此代码,那就有点糟糕了。

对于 2,我认为您需要传递一个 JSON,其中顶级元素与您的方法的属性名称匹配。所以检查 cURL 是否适用于类似的东西

{
"jsonPayload": "{\r\n  \"message_id\": \"12345\",\r\n  \"mobileNumber\": \"1234567890\",\r\n  \"text\": \"This is a test message\",\r\n  \"sim_card_number\": \"SIM123\",\r\n  \"reception_date\": \"2023-10-18 14:30:00\"\r\n}"
}

这个也很笨重,你有 JSON 接收。

通常我会创建一个辅助包装类来存储字段并传递该类的对象:

myMethod(Wrapper w)
。和 JSON 一样

{
    "w" : {
        "message_id" : "12345",
        "mobileNumber": "123"
    }
}

听起来你不能这样做,因为你无法控制传入的数据并且它包含保留关键字?

好吧,选择选项1,如果您需要重用此代码 - 创建一个接受参数的辅助方法。将

createIncomingTextMessage()
标记为 POST 并让它调用“正常”的
createIncomingTextMessage(String payload)
createIncomingTextMessage(Wrapper w)


0
投票

您还可以通过查看 saasguru Salesforce Labs 来增强您使用 Salesforce 的实践经验。这是一个非常棒的资源,旨在帮助您弥合理论知识和实际应用之间的差距。值得注意的是,saasguru Salesforce Labs 是免费访问的,这使得它成为任何想要提高技能的人的一个可用选项。

您可以按照自己的节奏随意探索它,看看它如何补充您的学习之旅。这里是链接 - https://www.saasguru.co/salesforce-labs-real-time-projects-for-practice/

© www.soinside.com 2019 - 2024. All rights reserved.