9

I get back JSON like the following:

         {
         Id = a0Ef0000002TPKVEA4;
         Name = a0Ef0000002TPKV;
         attributes =             {
             type = "Market__c";
             url = "/services/data/v29.0/sobjects/Market__c/a0Ef0000002TPKVEA4";
         };

The attributes portion doubles the data size. I've searched the docs but can't find a way to remove it. Here is the code I am using

 @HttpGet
 global static Aggregate doGet() {
     RestRequest req = RestContext.request;
     string userid = req.params.get('UserId');

     try {
         User user = [SELECT FirstName, LastName, Title, Email, Phone, MobilePhone,
          Street, City, State, PostalCode, Country, LevelOfCare__c, Username, PERNER__c
          FROM User WHERE Id = :userid];

          List<Market__c> markets = [SELECT Id, Name FROM Market__c];

         return new Aggregate(user, markets);         
     }
     catch (exception e) {
         return null;
     }
 }

 global class Aggregate {
     public User user {get; set;}
     public List<Market__c> markets {get; set;}

     public Aggregate(User u, List<Market__c> m) {
         user = u;
         markets = m;
     }
 } }
6

As it is custom Apex code, instead of directly returning the SObject, return a simple "bean" class that just has an Id and Name property with the values copied from the SObject:

public class Bean {
    public Id Id;
    public String Name;
    Bean(SObject sob) {
       this.Id = sob.Id;
       this.Name = (String) sob.get('Name');
    }
}

PS

Based on the posted code, it is the nested SObjects that you need to eliminate:

global class Aggregate {

    public Bean user {get; set;}
    public List<Bean> markets {get; set;}

    public Aggregate(User u, List<Market__c> ms) {
        user = new Bean(u);
        markets = new List<Bean>();
        for (Market__c m : ms) {
            markets.add(new Bean(m));
        }
    }
}
6
  • Thanks, but I thought I was. I've edited my question to include the code I am using. Apr 25 '14 at 14:49
  • 1
    What happens if you have 100+ fields? This method is not going to be elegant. Any thoughts on alternative, more dynamic way of achieving this? Sep 11 '14 at 7:41
  • 2
    @Bachovski You can JSON.serialize a Map<String, Object> so I assume (but don't know) that building such a map using describe information will work.
    – Keith C
    Sep 11 '14 at 7:55
  • I don't think that'll work because when you put your sObject as a value, it still has the attributes in it... I think @executeanon's anwer will do the trick Sep 11 '14 at 23:51
  • @Bachovski You would replace every SObject with a map, the parent one, the child ones, the grand-child ones and so on.
    – Keith C
    Sep 12 '14 at 7:56
10

It's a bit hacky, but you could remove the attributes by serialising and deserialising the SObjects to Maps, like this example:

Account acc = [Select Id, Name, (Select Id, Name From Contacts) From Account LIMIT 1];
Map<String,Object> accMap = (Map<String,Object>)JSON.deserializeUntyped(JSON.serialize(acc));

removeAttributes(accMap);

System.debug(JSON.serializePretty(accMap)); // et voila, no attributes

private void removeAttributes(Map<String,Object> jsonObj)  {
    for(String key : jsonObj.keySet()) {
        if(key == 'attributes') {
            jsonObj.remove(key);
        } else {
            if(jsonObj.get(key) instanceof Map<String,Object>) {
                removeAttributes((Map<String,Object>)jsonObj.get(key));
            }
            if(jsonObj.get(key) instanceof List<Object>) {
                for(Object listItem : (List<Object>)jsonObj.get(key)) {
                    if(listItem instanceof Map<String,Object>)  {
                        removeAttributes((Map<String,Object>)listItem);
                    }
                }
            }
        }
    }  
}

Probably not any more palatable that @KeithC's answer, but an alternative.

2
  • 1
    I've used this type of pattern before, and it's the best thing available right now if you need to be at all dynamic. Sep 11 '14 at 19:33
  • 1
    Has anyone done any Apex performance testing on this approach? We are considering this approach for situations where we're doing anything from 20-50 SOQL queries returning lots of results, as well as metadata for particular objects, so we don't want to make the Apex processing portion take any longer than necessary --- any idea how long a serialize/deserialize pair takes on a massive List<SObject>?
    – zachelrath
    Jan 20 '15 at 12:35
1

You can simply use JSONGenerator to get rid of the "attributes" element.

Refer to this link: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_json_jsongenerator.htm

0

Convert the object into a string and do not use standard salesforce serialize method.

Ex:

Account a = new Account(); String resString = String.valueof(a); return resString;

In this way we could not have \ in the response.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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