function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Brian SheaBrian Shea 

Problem formatting JSON response for Rest API (need to remove backslash "\")

I'm building a web service from my salesforce app and I'm running into some challenges formatting the JSON response that the service will generate. Specifically, the JSON contains backslash characters "\" that I want to remove. I've tried a few approaches; none of which have worked. Here are Apex snippets of the approaches I've tried:

Approach 1: return String
List<Location__c> locationList = Database.query(q);
String locationJSON = JSON.serialize(locationList);                 
locationJSON = locationJSON.replaceAll('"Physical_Address_City__c"', '"City"');
//Do more find/replace to update the rest of the keys...
return locationJSON;

With Approach 1 I am able to do a find/replace to format the keys in the JSON. But the JSON contains backslash characters "\" and does not contain a response header.

Results:
(no response header)
"[{\"City\":\"New York\"}]
 

Approach 2: use RestConext method
List<Location__c> locationList = Database.query(q); 
RestContext.response.addHeader('Content-Type', 'application/json'); 
RestContext.response.responseBody = Blob.valueOf(JSON.serialize(locationList));
With Approach 2, I am able to generate a JSON with a header and no backslashes "\" but I don't know how to rename the key values (for instance, Physical_Address_City__c --> City) using this approach. 

Results:
(response header)
"[{"Physical_Address_City__c":"New York"}]



Approach 3: Combination of Approach 1 and 2
List<Location__c> locationList = Database.query(q);        
String locationJSON = JSON.serialize(locationList);                 
locationJSON = locationJSON.replaceAll('"Physical_Address_City__c"', '"City"'); 
​//Do more find/replace to update the rest of the keys...
RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(JSON.serialize(locationJSON));

With Approach 3 I am able to generate a JSON with the response Header and transform the keys (Physical_Address_City__c --> City) but the JSON body still contains the backslash characters "\". And I'm serializing the JSON twice, which doesn't seem right.

Results:
(response header)
"[{\"City\":\"New York\"}]



Does anyone have thoughts on how to write this more elegantly and also remove the backslash characters? Thank you!

Brian
Best Answer chosen by Brian Shea
Ashish GargAshish Garg
Hi,

More time, we have the problems with string replace method. I have provided a most convinient way to convert list result in expected output JSON format:

1. First we have a instance wrapper class for Location object which will be having all corrosponding fields variables in it and we will map object record field values to class variables:
Public class Location {
	public String City;
	
	// ToDo: More variables here
	
	Public Location(Location__c loc) {
		this.City = loc.Physical_Address_City__c;
		
		// ToDo: More variables assignment
	}
}
2. Now, we need to query and map field values to instance wrapper variables and then serialize the result:
List<Location__c> locationList = Database.query(q);
List<Location> locationRecords = new List<Location>();

for(Location loc : locationList) {
	locationRecords.add(new Location(loc));
}
String locationJSON = JSON.serialize(locationRecords);

RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(locationJSON);

Thanks,
Ashish Garg
Email: ashish6mains@gmail.com
Mob: +91-8952827377
 

All Answers

Ashish GargAshish Garg
Hi,

More time, we have the problems with string replace method. I have provided a most convinient way to convert list result in expected output JSON format:

1. First we have a instance wrapper class for Location object which will be having all corrosponding fields variables in it and we will map object record field values to class variables:
Public class Location {
	public String City;
	
	// ToDo: More variables here
	
	Public Location(Location__c loc) {
		this.City = loc.Physical_Address_City__c;
		
		// ToDo: More variables assignment
	}
}
2. Now, we need to query and map field values to instance wrapper variables and then serialize the result:
List<Location__c> locationList = Database.query(q);
List<Location> locationRecords = new List<Location>();

for(Location loc : locationList) {
	locationRecords.add(new Location(loc));
}
String locationJSON = JSON.serialize(locationRecords);

RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(locationJSON);

Thanks,
Ashish Garg
Email: ashish6mains@gmail.com
Mob: +91-8952827377
 
This was selected as the best answer
Brian SheaBrian Shea

Hi Ashish,
Thank you! I created Public class Location in my application and began filling in the field mapping:

Public class Location {
public String City;
public String Street1;
public String Street2;
    
Public Location(Location__c loc) {
this.City = loc.Physical_Address_City__c;
this.Street1 = loc.Physical_Address_Street_1__c;
this.Street2 = loc.Physical_Address_Street_2__c;    
}
}


but when I try to reference Location in my original apex class LocationSearch I'm getting an error:

Compile Error: Constructor not defined: [Location].<Constructor>(Location) at line 52 column 33

Here's the offending code in the LocationSearch class:

List<Location__c> locationList = Database.query(q);
        List<Location> locationRecords = new List<Location>();

        for(Location loc : locationList) {
            locationRecords.add(new Location(loc));
        }
        
        String locationJSON = JSON.serialize(locationRecords);

        RestContext.response.addHeader('Content-Type', 'application/json');
        RestContext.response.responseBody = Blob.valueOf(locationJSON);
I believe this line is the issue, but not sure how to resolve it:
locationRecords.add(new Location(loc));

Any ideas?

Thanks!
Brian
Brian SheaBrian Shea
Found the issue. The line:
for(Location loc : locationList) {
should be
for(Location__c loc : locationList) {

Corrected code below:
List<Location__c> locationList = Database.query(q);
List<Location> locationRecords = new List<Location>();
 for(Location__c loc : locationList) {
            locationRecords.add(new Location(loc));
}
        
String locationJSON = JSON.serialize(locationRecords);
 
RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(locationJSON);

Thanks again Ashish. This approach is *much* better than the search/replace String approach.
Brian SheaBrian Shea
One more follow-up question on the mapping approach above.
The SELECT statement in my SOQL query contains the following function:
DISTANCE(Geolocation__c, GEOLOCATION(:lat, :lng), \'mi\')

I'm havng an issue mapping the results of this function in Public Class Location. Here's what I'm trying:
Public class Location {
	    public Decimal Distance;
	    // ToDo: More variables here

	    Public Location(Location__c loc) {
	           this.Distance = loc.expr0;
	           // ToDo: More variables assignment
            }
}
But I'm getting the following error:
Error: Compile Error: Invalid field expr0 for SObject Location__c at line 22 column 33

I also tried aliasing the Distance results to DISTANCE in my SELECT statement and reference DISTANCE
this.Distance = loc.DISTANCE;
But that didn't work either. Same error message.

The mapping is expecting a field, but I'm passing it the results of a function. Any recommendations for how to work around this?

Thanks!