Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm developing a custom apex REST API and running into an issue annotating my getAppDefaults method with @HttpGet. When I remove the annotation and run a test class against the getAppDefaults method, I get my Map of Maps back. But I'd like this returned as a JSON structure from the GET request.

Also, if I change the method to return a String and JSON.serialize(appDefaults), I get a stringified result back from the REST requested (ie, the annotation works fine but I would like to return a JSON structure, not a string).

@RestResource(urlMapping='/v1.0/AppDefaults/*')
global with sharing class hbAppUserDefaults {

    ... //other internal methods

    @HttpGet
    global static Map<String, Map<String,Object>> getAppDefaults() {
        Map<String, Map<String,Object>> appDefaults = new Map<String, Map<String,Object>>();

        Map<String, String> u = new Map<String, String>(getUserDefaults());        
        Map<String, Object> cases = new Map<String, Object>(getCases());
        Map<String, Object> dashboards = new Map<String, Object>(getDashboards());
        Map<String, Object> robots = new Map<String, Object>(getRobots());

        appDefaults.put('User', u);
        appDefaults.put('Cases', cases);
        appDefaults.put('Dashboards', dashboards);
        appDefaults.put('Robots', robots);

        return appDefaults;
    }    

}

The compile error I get with the code above is as follows: enter image description here

Any help is greatly appreciated!

share|improve this question
up vote 5 down vote accepted

A technique I have used for this sort of case is to directly set the JSON in the response rather than relying on the framework to do the serialization (which as you have noticed has some limitations):

@HttpGet 
global static void getAppDefaults() {

    RestResponse res = RestContext.response;
    if (res == null) {
        res = new RestResponse();
        RestContext.response = res;
    }
    try {
        Map<String, Map<String,Object>> appDefaults = ...
        ..
        res.responseBody = Blob.valueOf(JSON.serialize(appDefaults));
        res.statusCode = 200;
    } catch (Exception e) {
        res.responseBody = Blob.valueOf(
                String.valueOf(e) + '\n\n' + e.getStackTraceString()
                );
        res.statusCode = 500;
    }
}

This avoids the double encoding that returning String from the method produces.

A further advantage of the above pattern (at least in the context of managed packages) is that if you want to change the structure of the JSON in the future you can; relying on the method signature you cannot because global methods can't be changed once packaged.

A bit more information in An @RestResource Apex class that returns multiple JSON formats.

share|improve this answer
    
+1 You beated me @Keith in answering this one, was almost putting something similar :) – Abhinav Gupta Jan 9 at 12:48
    
Thanks both!! Appreciate the fast feedback. I've implemented the above and it works exactly like I expected. – Rob Goldiez Jan 9 at 12:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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