Wrapper Classes & JSON Parsing – Real API Examples

Wrapper classes help structure data, especially when working with APIs. Learn how to parse JSON responses and serialize objects for API requests.

1. Creating Wrapper Classes

Simple Wrapper Class


public class AccountWrapper {
    public String id;
    public String name;
    public String email;
    public Integer revenue;
    
    public AccountWrapper(Account acc) {
        this.id = acc.Id;
        this.name = acc.Name;
        this.email = acc.Email__c;
        this.revenue = (Integer) acc.Annual_Revenue__c;
    }
}

// Usage
Account acc = [SELECT Id, Name, Email__c, Annual_Revenue__c FROM Account LIMIT 1];
AccountWrapper wrapper = new AccountWrapper(acc);
String json = JSON.serialize(wrapper);
System.debug(json);
// Output: {"email":"[email protected]","id":"001xxxxxxx","name":"Acme Corp","revenue":1000000}
  

2. Parsing JSON Responses from APIs

Real Example: Weather API Response


// Wrapper classes for API response
public class WeatherResponse {
    public String location;
    public Double temperature;
    public String condition;
    public Double humidity;
    public List<Forecast> forecast;
    
    // Maps JSON field names to Apex variable names
    public WeatherResponse(Map<String, Object> data) {
        this.location = (String) data.get('location');
        this.temperature = (Double) data.get('temp');
        this.condition = (String) data.get('condition');
        this.humidity = (Double) data.get('humidity');
    }
}

public class Forecast {
    public String date;
    public String condition;
    public Double highTemp;
    public Double lowTemp;
}

// API Call
public class WeatherService {
    public static WeatherResponse getWeather(String city) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('callout:WeatherAPI/current?city=' + city);
        request.setMethod('GET');
        
        HttpResponse response = http.send(request);
        
        if (response.getStatusCode() == 200) {
            // Parse JSON response
            Map<String, Object> responseBody = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            WeatherResponse weather = new WeatherResponse(responseBody);
            return weather;
        }
        
        return null;
    }
}
  

3. REST API Integration Example

Stripe Payment Integration


public class StripePaymentProcessor {
    
    // Request wrapper
    public class PaymentRequest {
        public Decimal amount;
        public String currency;
        public String description;
        public String customer_id;
    }
    
    // Response wrapper
    public class PaymentResponse {
        public String id;
        public String status;  // succeeded, failed, pending
        public Decimal amount;
        public String error_message;
    }
    
    public static PaymentResponse processPayment(Account acc, Decimal amount) {
        try {
            PaymentRequest req = new PaymentRequest();
            req.amount = amount * 100;  // Convert to cents
            req.currency = 'usd';
            req.description = 'Payment for ' + acc.Name;
            req.customer_id = acc.Stripe_Customer_ID__c;
            
            Http http = new Http();
            HttpRequest request = new HttpRequest();
            request.setEndpoint('callout:StripeAPI/v1/charges');
            request.setMethod('POST');
            request.setHeader('Content-Type', 'application/json');
            request.setBody(JSON.serialize(req));
            
            HttpResponse response = http.send(request);
            
            if (response.getStatusCode() == 200) {
                PaymentResponse result = (PaymentResponse) JSON.deserialize(
                    response.getBody(), 
                    PaymentResponse.class
                );
                return result;
            } else {
                PaymentResponse errorResult = new PaymentResponse();
                errorResult.status = 'failed';
                errorResult.error_message = response.getBody();
                return errorResult;
            }
        } catch (Exception e) {
            PaymentResponse errorResult = new PaymentResponse();
            errorResult.status = 'failed';
            errorResult.error_message = e.getMessage();
            return errorResult;
        }
    }
}
  

4. Complex Nested Wrappers

GitHub API Response


public class GitHubUser {
    public String login;
    public Integer id;
    public String avatar_url;
    public String bio;
    public Integer public_repos;
    public List<Repository> repositories;
}

public class Repository {
    public String name;
    public String description;
    public String url;
    public Boolean is_private;
    public Integer stargazers_count;
}

// Parsing nested JSON
public class GitHubService {
    public static GitHubUser getUserProfile(String username) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://api.github.com/users/' + username);
        request.setMethod('GET');
        request.setHeader('Accept', 'application/vnd.github.v3+json');
        
        HttpResponse response = http.send(request);
        
        if (response.getStatusCode() == 200) {
            GitHubUser user = (GitHubUser) JSON.deserialize(
                response.getBody(), 
                GitHubUser.class
            );
            return user;
        }
        return null;
    }
}
  

5. Handling Special Field Names

JSON often uses different naming conventions than Apex. Use @AuraEnabled or custom deserialization:


public class ApiResponse {
    @AuraEnabled
    public String first_name;  // Maps from JSON "first_name"
    
    @AuraEnabled  
    public String last_name;   // Maps from JSON "last_name"
    
    @AuraEnabled
    public String email_address;
}

// Or manually map field names
public class CustomMapping {
    public String firstName;
    public String lastName;
    
    public CustomMapping(Map<String, Object> data) {
        this.firstName = (String) data.get('first_name');
        this.lastName = (String) data.get('last_name');
    }
}
  

6. Serializing Objects to JSON


public class JsonSerialization {
    
    public static void example() {
        // Create objects
        Account acc = new Account(Name = 'Acme Corp', Phone = '555-1234');
        
        // Serialize to JSON
        String json = JSON.serialize(acc);
        System.debug(json);
        // Output: {"attributes":{"type":"Account"},"Name":"Acme Corp","Phone":"555-1234"}
        
        // Serialize with options
        String json2 = JSON.serializePretty(acc);  // Pretty print
        
        // Serialize custom wrapper
        AccountWrapper wrapper = new AccountWrapper(acc);
        String json3 = JSON.serialize(wrapper);
    }
}
  

7. Real-World Example: Salesforce REST API


public class SalesforceRESTClient {
    
    public class SalesforceRecord {
        public String Id;
        public String Name;
        public Map<String, Object> fields;
    }
    
    public static SalesforceRecord getRecord(String sObjectType, String recordId) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        
        String endpoint = 'callout:Salesforce_Instance/services/data/v57.0/sobjects/' + 
                          sObjectType + '/' + recordId;
        
        request.setEndpoint(endpoint);
        request.setMethod('GET');
        request.setHeader('Authorization', 'Bearer ' + getAccessToken());
        
        HttpResponse response = http.send(request);
        
        if (response.getStatusCode() == 200) {
            Map<String, Object> record = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            
            SalesforceRecord result = new SalesforceRecord();
            result.Id = (String) record.get('Id');
            result.Name = (String) record.get('Name');
            result.fields = record;
            
            return result;
        }
        return null;
    }
    
    private static String getAccessToken() {
        // Implementation to get access token
        return 'your_token';
    }
}
  

8. Error Handling with JSON


public class JsonErrorHandling {
    
    public static void parseWithErrorHandling(String jsonString) {
        try {
            Map<String, Object> data = (Map<String, Object>) JSON.deserializeUntyped(jsonString);
            System.debug('Parsed successfully: ' + data);
        } catch (JSONException e) {
            System.debug('Invalid JSON: ' + e.getMessage());
        } catch (Exception e) {
            System.debug('Unexpected error: ' + e.getMessage());
        }
    }
}
  

Key Takeaways