Advanced 18 min read

JSON Serialization and Callouts

By the end of this lesson, you'll be able to:

  • Make an HTTP callout from Apex using Http, HttpRequest, and HttpResponse
  • Parse a JSON response using JSON.deserializeUntyped for dynamic shapes
  • Parse a JSON response into a typed Apex class using JSON.deserialize

Prerequisites: "Named Credentials and External Credentials"

Making a Callout

HttpRequest request = new HttpRequest();
request.setEndpoint('callout:Weather_API/current?city=Cape+Town');
request.setMethod('GET');
request.setHeader('Content-Type', 'application/json');

Http http = new Http();
HttpResponse response = http.send(request);

HttpRequest describes the call (endpoint, method, headers); Http.send() actually performs it and returns an HttpResponse — this is the Apex equivalent of the browser's fetch, used here because only Apex can perform the callout at all (Lesson 1).

Parsing JSON Responses

// Dynamic/unknown shape — a generic Map
Map<String, Object> data = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
Decimal temperature = (Decimal) data.get('temperature');
// Known, stable shape — a typed Apex class
public class WeatherResponse {
    public Decimal temperature;
    public String conditions;
}

WeatherResponse weather = (WeatherResponse) JSON.deserialize(response.getBody(), WeatherResponse.class);

JSON.deserializeUntyped produces a generic Map<String, Object> — flexible, but every value needs an explicit cast and there's no compile-time checking of property names. JSON.deserialize into a matching Apex class is preferred whenever the response shape is stable and known in advance — it gives compile-time-checked, typed property access instead.

A Worked Example

public with sharing class WeatherService {
    public static WeatherSummary getCurrentWeather(String city) {
        HttpRequest request = new HttpRequest();
        request.setEndpoint('callout:Weather_API/current?city=' + EncodingUtil.urlEncode(city, 'UTF-8'));
        request.setMethod('GET');

        HttpResponse response = new Http().send(request);
        WeatherResponse raw = (WeatherResponse) JSON.deserialize(response.getBody(), WeatherResponse.class);

        return new WeatherSummary(raw.temperature, raw.conditions);
    }
}

The raw API response is deserialized into an internal WeatherResponse class, then mapped into a WeatherSummary wrapper (Module 7's DTO pattern) — exactly the kind of clean boundary that decouples the component from the external API's own response shape.

Exercise

Write the Apex code to deserialize a JSON string jsonBody into a typed StockQuote class with fields symbol (String) and price (Decimal).

Show hint

Use JSON.deserialize with a cast.

APEX

Exercise

Challenge: explain, as a comment, why JSON.deserialize into a typed class is generally preferred over JSON.deserializeUntyped when the response shape is known and stable.

Show hint

Think about what each approach checks (or doesn't check) at compile time.

APEX

JSON Serialization and Callouts Quiz

1. What class actually performs an HTTP callout in Apex?

2. What does JSON.deserializeUntyped return?

3. When is JSON.deserialize into a typed class generally preferred over deserializeUntyped?

4. What benefit does a typed class give over a generic Map when parsing JSON?

5. Why is the raw API response mapped into a separate wrapper class (WeatherSummary) rather than returned directly?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

Http/HttpRequest/HttpResponse perform the actual callout, and Apex's JSON utilities turn the raw response text into either a flexible generic structure or a strongly-typed class, depending on how much the response shape is known in advance.