6

I follow Creating REST APIs

And I would like to response data as:

{
    "list": [
        {
            "id": "KH001"
        },
        ...
    ]
}

My Class look like this ( everything just work as normal if I used items instead of list as variable name ) I am wondering would be possible if the response above is really required ?

@RestResource(urlMapping='/kh/*')
global with sharing class RESTKhController {
    @HttpGet
    global static ResponseWrapperClass getList() {
        return new ResponseWrapperClass();
    }

    global class ResponseWrapperClass {
        global List<DataWrapperClass> list; // ERROR unexpected token: 'list'
    }

    global class DataWrapperClass {
        global String id;
    }
}

4 Answers 4

3

Salesforce Apex and other languages like Java, C etc will give you errors when you try to use reserved words.

However as you said that this response is really required so here is what I suggest.

  1. Rename the list to something unique example: list_replace_me

    global List<DataWrapperClass> list_replace_me;
    
  2. Instead of returning the wrapper from your GET method, return a string.

    global static string getList() { 
    //Manually serialize this object
    
    new ResponseWrapperClass(); } 
    
  3. Manually serialize the object by JsonGenerator class to get a string, or use JSON.serialize(inputobject) which return a string.

  4. Replace "list_replace_me" with "list" using String.replace function.

  5. Return the new String after replacing.

Json Generator

2
  • That a good idea. Seem this is the only way ?
    – liratanak
    Sep 18, 2015 at 4:31
  • Yes, this is the one way I can think of. The other way is not to use reserved words. :)
    – manjit5190
    Sep 19, 2015 at 18:26
3

Use JSON2Apex with the 'Create explicit parse code' option enabled. This will produce code like so:

//
// Generated by JSON2Apex http://json2apex.herokuapp.com/
//

public class MyList {
    // ...boilerplate...

    public class List_Z {
        public String id {get;set;}

        public List_Z(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'id') {
                            id = parser.getText();
                        } else {
                            System.debug(LoggingLevel.WARN, 'List_Z consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

    public List<List_Z> list {get;set;}

    public MyList(JSONParser parser) {
        while (parser.nextToken() != JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != JSONToken.VALUE_NULL) {
                    if (text == 'list') {
                        list = new List<List_Z>();
                        while (parser.nextToken() != JSONToken.END_ARRAY) {
                            list.add(new List_Z(parser));
                        }
                    } else {
                        System.debug(LoggingLevel.WARN, 'Root consuming unrecognized property: '+text);
                        consumeObject(parser);
                    }
                }
            }
        }
    }

    //...etc...

Just replace all occurrences of the list member variable with list_z (or whatever you like), and you're off to the races:

//
// Generated by JSON2Apex http://json2apex.herokuapp.com/
// Hand-modified by @metadaddy :-)
//

public class MyList {
    // ...boilerplate...

    public class List_Z {
        public String id {get;set;}

        public List_Z(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'id') {
                            id = parser.getText();
                        } else {
                            System.debug(LoggingLevel.WARN, 'List_Z consuming unrecognized property: '+text);
                            consumeObject(parser);
                        }
                    }
                }
            }
        }
    }

    public List<List_Z> list_z {get;set;}

    public MyList(JSONParser parser) {
        while (parser.nextToken() != JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != JSONToken.VALUE_NULL) {
                    if (text == 'list') {
                        list_z = new List<List_Z>();
                        while (parser.nextToken() != JSONToken.END_ARRAY) {
                            list_z.add(new List_Z(parser));
                        }
                    } else {
                        System.debug(LoggingLevel.WARN, 'Root consuming unrecognized property: '+text);
                        consumeObject(parser);
                    }
                }
            }
        }
    }

    //...etc...

Note - you'll also need to move the test code into its own class. Superfell or I need to go back and fix that. We should also rename the member variable when it clashes with a reserved word.

Anyway - now you can create a MyList from JSON like so:

MyList l = MyList.parse(json);
0

This may be 6 years too late... but might help someone else... I was creating a web service for a specific JSON being sent to me (so I do not have the option of changing the names of the values sent to me). I was able to utilize a class using Map<String,String> to get a generic map of the incoming request.

Specifically, my example:

{
    "message": {
        "sms": {
            "from": "12155551212",
            "to": "12155552121"
        },
        "body": "Help"
    }
}

I couldn't use "to" or "from" as variable names within my "sms" class... so I implemented this way:

global class Message_Incoming { 
    Map<String,String> sms;
    String body;
   
    public Message_Incoming () {
        sms = new Map<String,String>{ 'from' => null, 'to' => null };
    }
}

@HttpPost
global static Message_Response doPost (Message_Incoming message) { ... }

It successfully parses the incoming JSON into the class variable, and the "sms" is now a map so I can get the value like this: message.sms.get('from')

1
  • Thanks you! :-D
    – liratanak
    Apr 7, 2021 at 7:20
-1

This is 3 years late, but if anyone ever sees this, you can also use responseString = response.getBody() and make a string of the response, then use responseString.Replace('"reservedWord":', '"yourNewWord":') to map response fields to a wrapper class.

1
  • Hi, just curious I see this post was downvoted. Is replacing string in response bad practice?
    – helpifell
    Sep 4, 2019 at 21:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .