0

I am confused about some of the information in the developer Guide regarding setting up a REST Service POST method. I've set up my service similarly to the following example from the Developer Guide:

@RestResource(urlMapping='/user_defined_type_example/*')
global with sharing class MyOwnTypeRestResource {

@HttpPost
global static MyUserDefinedClass echoMyType(MyUserDefinedClass ic) {
    return ic;
}

global class MyUserDefinedClass {

    global String string1;
    global String string2 { get; set; }
    private String privateString;
    global transient String transientString;
    global static String staticString;

}

}

This is the basics of my POST service. The only difference is that I use a list of user-defined class objects. Its likely these will only come one at a time, but in the interests of bulkification I figure you go with a list.

@RestResource(urlMapping='/RESTServices/*')

global class newService{

global class UserData{ // the user-defined class
    public string username;
    public string email;
    public string phone;
}

@HttpPost
global static String postUserData(UserData[] userData){
    //...do stuff
    return JSONString;
}

}

OK, the Guide says: "Apex REST deserializes request data into public, private, or global class member variables of the user-defined type, unless the variable is declared as static or transient." - None of my variables are static or transient.

The service is expecting a list of UserData objects and I'm under the impression that APEX will receive the JSON string from the request body and deserialize it into a list of UserData objects.

1) Does this look right?? All the examples for Post methods that I see are sending the primitives as parameters into the POST method, as opposed to one of these user-defined classes that the Guide's example uses. I could do that, but the number of parameters is substantially larger than what I have provided in my example. So, is my assumption that APEX will received the JSON body in the request, and deserialize it into a list of userdata objects correct?? Or, do I really need to write out all those parameters? Or is something else supposed to happen that I'm missing completely?

2) In my test, I have created a JSON string that is validating and I want to get it into the test. I can't just add the string to the requestBody, as it asks me to make it a blob: req.requestBody - blob.valueOf(JSONRequestString); Is this the correct way to add the JSON String into the request?? That is, will the process see the requestbody as it comes in, convert the blob into a string, then deserialize the string into the UserData class object? My gut tells me 'NO!'. So, if not, how do I do this?

Any help from someone who has done this is much appreciated.

  • to question (1) YES; automatic deserialization will go into the list of UserData if the POST body is a JSON array; (2) for testing, assume SFDC deserializes correctly - simply mock the array of UserData before Test.startTest() – cropredy Sep 26 '17 at 1:22
2

1) Does this look right?? All the examples for Post methods that I see are sending the primitives as parameters into the POST method, as opposed to one of these user-defined classes that the Guide's example uses. I could do that, but the number of parameters is substantially larger than what I have provided in my example.

Yes, you can use non-primitives. Also, there is an intrinsic limit of 32 parameters, so if you think you might exceed that, definitely use an object.

So, is my assumption that APEX will received the JSON body in the request, and deserialize it into a list of userdata objects correct?? Or, do I really need to write out all those parameters? Or is something else supposed to happen that I'm missing completely?

You can use a JSON or XML payload, your choice. The system is smart enough to parse the parameters either way.

2) In my test, I have created a JSON string that is validating and I want to get it into the test. I can't just add the string to the requestBody, as it asks me to make it a blob: req.requestBody - blob.valueOf(JSONRequestString); Is this the correct way to add the JSON String into the request?? That is, will the process see the requestbody as it comes in, convert the blob into a string, then deserialize the string into the UserData class object? My gut tells me 'NO!'. So, if not, how do I do this?

For a unit test, you call it like a normal method:

newService.UserData[] data = new newService.UserData[0];
data.add(new newService.UserData(...));
newService.postUserData(data);

You only need to use the HttpCalloutMock interface when you're mocking callouts to external systems. There is no need to verify that the behavior of @RestResource works, so you don't need to mock a full callout stack for the purposes of testing your code.

  • Thanks for your response!! So, as far as testing, I created a JSON string in the test, which I blobbed into the RestRequest body. I see that I could just create my own Userdata class instance with the values and run the method, but is there some way to test from the RestRequest to see the backend process deserialize the request body? – VeMan Sep 26 '17 at 7:25
  • @VeMan You'd end up calling JSON.deserialize. If you wanted to pretend it was a real callout, you'd write an HttpCalloutMock that would call JSON.deserialize and then call your method. In other words, you would still be constructing your own data. If you wanted to use your JSON string, though, you could deserialize it yourself with JSON.deserialize. It doesn't matter how the UserData gets constructed, in the end, but you will be calling your code as a static method no matter how you get there. – sfdcfox Sep 26 '17 at 13:20

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.