JSON payload of REST method serialized twice

apexjson

I have a very simple class and Web Service. The resulting JSON shows that the payload is getting serialized twice. Could you please point out my error?

   public class JSONFactory {
    public Integer id;
    public String name;
    public String lastName;
    public JSONFactory(Integer a, String b, String c){
        this.id = a;
        this.name = b;
        this.lastName = c;
        }
    }

    @RestResource(urlMapping='/Johnny')
    global class WebServiceFactory {
        @HttpGet
        global static String getRecord() {
            List<JSONFactory> JSONs = new List<JSONFactory>();
            for(integer i = 0; i<4; i++){
                JSONs.add(new JSONFactory(i, 'Jan' + i, 'Test' + i));
            
            }
            return JSON.serialize(JSONs);
        }
    }

Resulting JSON (serialized twice):

[{\"name\":\"Jan0\",\"lastName\":\"Test0\",\"id\":0},
 {\"name\":\"Jan1\",\"lastName\":\"Test1\",\"id\":1},
 {\"name\":\"Jan2\",\"lastName\":\"Test2\",\"id\":2},
 {\"name\":\"Jan3\",\"lastName\":\"Test3\",\"id\":3}]

Best Answer

When you directly return a value (here, a String) from a @RestResource class, the platform automatically serializes that value for you. That's where the double-serialization is coming from.

You should always either:

Return the value you want serialized, and let the platform handle it:

    @RestResource(urlMapping='/Johnny')
    global class WebServiceFactory {
        @HttpGet
        global static List<JSONFactory> getRecord() {
            List<JSONFactory> JSONs = new List<JSONFactory>();
            for(integer i = 0; i<4; i++){
                JSONs.add(new JSONFactory(i, 'Jan' + i, 'Test' + i));
            
            }
            return JSONs;
        }
    }

or directly set the serialized data in the RestContext object, and do not return a value:

    @RestResource(urlMapping='/Johnny')
    global class WebServiceFactory {
        @HttpGet
        global static void getRecord() {
            List<JSONFactory> JSONs = new List<JSONFactory>();
            for(integer i = 0; i<4; i++){
                JSONs.add(new JSONFactory(i, 'Jan' + i, 'Test' + i));
            
            }
            RestContext.response.responseBody = Blob.valueOf(JSON.serialize(JSONs));
        }
    }

One place you can find this in the documentation is in RestResponse under responseBody:

The response is either the serialized form of the method return value or it's the value of the responseBody property based on the following rules:

  • If the method returns void, then Apex REST returns the response in the responseBody property.
  • If the method returns a value, then Apex REST serializes the return value as the response.
Related Topic