apex-json-serialization

Use when serializing Apex objects to JSON strings or deserializing JSON responses into Apex types — especially for callout payloads, integration parsing, and controlling null field output. Trigger keywords: 'suppress null fields JSON Apex', 'deserialize JSON into Apex class', 'JSON parse unknown shape', 'TypeException JSON deserialize', 'JSONGenerator streaming'. NOT for REST endpoint response shaping (use apex-rest-services), NOT for Apex remote actions returning JSON to LWC.

Best use case

apex-json-serialization is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when serializing Apex objects to JSON strings or deserializing JSON responses into Apex types — especially for callout payloads, integration parsing, and controlling null field output. Trigger keywords: 'suppress null fields JSON Apex', 'deserialize JSON into Apex class', 'JSON parse unknown shape', 'TypeException JSON deserialize', 'JSONGenerator streaming'. NOT for REST endpoint response shaping (use apex-rest-services), NOT for Apex remote actions returning JSON to LWC.

Teams using apex-json-serialization should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/apex-json-serialization/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/apex/apex-json-serialization/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/apex-json-serialization/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How apex-json-serialization Compares

Feature / Agentapex-json-serializationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when serializing Apex objects to JSON strings or deserializing JSON responses into Apex types — especially for callout payloads, integration parsing, and controlling null field output. Trigger keywords: 'suppress null fields JSON Apex', 'deserialize JSON into Apex class', 'JSON parse unknown shape', 'TypeException JSON deserialize', 'JSONGenerator streaming'. NOT for REST endpoint response shaping (use apex-rest-services), NOT for Apex remote actions returning JSON to LWC.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Apex JSON Serialization

Use this skill when converting Apex objects to JSON strings for outbound callouts or parsing JSON responses from external APIs into Apex types. Covers the full JSON class family: `JSON.serialize/deserialize`, `JSON.deserializeUntyped`, `JSONGenerator`, and `JSONParser`.

---

## Before Starting

Gather this context before working on anything in this domain:

- Confirm whether the JSON shape is known at compile time (use typed deserialization) or dynamic (use `deserializeUntyped` or `JSONParser`).
- Check heap constraints: large JSON payloads count toward the 6 MB sync / 12 MB async heap limit.
- Identify whether null fields in the output will cause downstream parsing failures — if so, use `suppressApexObjectNulls`.

---

## Core Concepts

### JSON.serialize and suppressApexObjectNulls

`JSON.serialize(obj)` converts any Apex object to a JSON string. By default it includes all fields, including those with null values. Pass `true` as the second argument — `JSON.serialize(obj, true)` — to suppress null fields recursively across the entire object graph. LLMs routinely omit this argument, producing bloated payloads that fail strict JSON schema validation on the receiving end.

`suppressApexObjectNulls` applies recursively to nested custom objects: if an outer object contains a non-null nested object that has null fields, those inner nulls are also suppressed. Static fields are **not** serialized by `JSON.serialize` — only public instance fields.

### JSON.deserialize and TypeException

`JSON.deserialize(jsonString, Type.class)` deserializes into a typed Apex object. Extra JSON fields that don't match the Apex type are silently ignored. However, a type mismatch on a field that *does* exist (e.g., JSON has a String where Apex expects an Integer) throws `System.TypeException` at runtime — it is not silently tolerated. Always wrap external-data deserialization in try/catch for `TypeException`.

`JSON.deserializeStrict(jsonString, Type.class)` (API v45+) rejects JSON with extra fields — use when schema adherence must be enforced.

### JSON.deserializeUntyped

`JSON.deserializeUntyped(jsonString)` returns `Object`, which at runtime is `Map<String, Object>` for JSON objects, `List<Object>` for arrays, or a primitive. You must cast explicitly:

```apex
Map<String, Object> root = (Map<String, Object>) JSON.deserializeUntyped(response);
List<Object> items = (List<Object>) root.get('items');
```

Use this when the JSON shape is not known at compile time or varies between responses.

### JSONGenerator and JSONParser

`JSONGenerator` writes JSON token by token — use for very large payloads or precise control over field ordering. Pattern: `JSON.createGenerator(prettyPrint)` → `writeStartObject/writeFieldName/writeString` → `getAsString()`.

`JSONParser` reads JSON token by token using `nextToken()` returning `JSONToken` enum values. `parser.readValueAs(SomeClass.class)` deserializes from the current parser position — useful for large heterogeneous arrays without loading the full structure into heap.

---

## Common Patterns

### Outbound callout payload with null suppression

**When to use:** Sending a structured Apex object as a POST body to a REST API that rejects null fields.

**How it works:**

```apex
public class OrderPayload {
    public String orderId;
    public Decimal amount;
    public String couponCode; // may be null
}
OrderPayload p = new OrderPayload();
p.orderId = '12345';
p.amount = 99.95;
// couponCode stays null — omitted from output
String body = JSON.serialize(p, true); // {"orderId":"12345","amount":99.95}
```

**Why not the alternative:** `JSON.serialize(p)` without the flag produces `{"orderId":"12345","amount":99.95,"couponCode":null}`, which fails strict schema validation.

### Deserializing a typed response safely

**When to use:** Parsing a known-shape JSON response from an HTTP callout.

**How it works:**

```apex
HttpResponse res = http.send(req);
try {
    MyResponseWrapper wrapper = (MyResponseWrapper) JSON.deserialize(
        res.getBody(), MyResponseWrapper.class
    );
} catch (JSONException e) {
    // malformed JSON
} catch (System.TypeException e) {
    // shape mismatch — log and surface to caller
}
```

---

## Decision Guidance

| Situation | Recommended Approach | Reason |
|---|---|---|
| JSON shape matches Apex class | `JSON.deserialize(str, MyClass.class)` | Typed, safe, readable |
| JSON shape unknown or varies | `JSON.deserializeUntyped(str)` + cast | Flexible, no compile-time type needed |
| Need to suppress null fields | `JSON.serialize(obj, true)` | Omits nulls recursively |
| Very large payload or streaming write | `JSONGenerator` | Controls memory and token order |
| Large heterogeneous JSON array | `JSONParser` + `readValueAs()` | Avoids loading full structure into heap |
| Strict schema enforcement on input | `JSON.deserializeStrict()` | Rejects extra fields |

---

## Recommended Workflow

1. **Determine direction**: serialize (Apex → JSON) or deserialize (JSON → Apex).
2. **For serialization**: create or reuse an Apex wrapper; decide if null suppression is needed; use `JSON.serialize(obj, suppressNulls)`.
3. **For typed deserialization**: define Apex class matching JSON shape; wrap `JSON.deserialize()` in try/catch for `TypeException`.
4. **For untyped deserialization**: use `JSON.deserializeUntyped()` and navigate `Map<String,Object>` / `List<Object>` with explicit casts.
5. **For streaming large payloads**: use `JSONGenerator` for writes, `JSONParser` for reads.
6. **Validate heap impact**: estimate payload size; payloads over 1 MB in sync context warrant chunking or async processing.
7. **Test error paths**: include a test passing unexpected JSON to confirm `TypeException` is caught without leaking stack traces.

---

## Review Checklist

- [ ] `suppressApexObjectNulls` (`true`) passed where null fields must be omitted
- [ ] `JSON.deserialize` wrapped in try/catch for `TypeException`
- [ ] `deserializeUntyped` result cast explicitly before use
- [ ] Static fields not expected in serialized output
- [ ] Large payloads sized against heap limit (6 MB sync / 12 MB async)
- [ ] `JSON.deserializeStrict` used where extra fields must be rejected

---

## Salesforce-Specific Gotchas

1. **suppressApexObjectNulls is recursive** — it suppresses nulls in nested custom objects, not just the top level. If you expect a nested object to include null fields for schema reasons, this flag silently drops them.
2. **TypeException on type mismatch, NOT on extra fields** — `JSON.deserialize` silently ignores extra JSON fields, but throws `TypeException` if a matching field has the wrong data type. Developers expect the extra-field tolerance to extend to type mismatches too.
3. **Static fields excluded from serialization** — only public instance fields are serialized. Static, transient, and `@TestVisible`-only fields are excluded silently.

---

## Output Artifacts

| Artifact | Description |
|---|---|
| Apex wrapper class | Typed class matching JSON shape for `JSON.deserialize` |
| Serialized JSON string | Body string for HTTP callout or storage |
| `check_apex_json_serialization.py` | Validator confirming required method coverage |

---

## Related Skills

- apex-rest-services — for shaping REST endpoint responses and `@RestResource` handlers
- callouts-and-http-integrations — for HTTP callout mechanics, Named Credentials, and timeout handling
- apex-wrapper-class-patterns — for designing wrapper classes used in JSON serialization

Related Skills

apex-managed-sharing-patterns

8
from PranavNagrecha/AwesomeSalesforceSkills

Grant row-level access programmatically via __Share records when declarative sharing rules cannot express the policy. NOT for OWD, role hierarchy, or criteria-based sharing rule design.

lwc-imperative-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Call Apex methods imperatively from LWC — on button click, lifecycle hooks, or conditional logic. Covers import syntax, cacheable vs non-cacheable, async/await patterns, error handling, loading states, and Promise.all. NOT for wire service (use wire-service-patterns) and NOT for testing Apex mocks (use lwc-testing).

dataweave-for-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when transforming structured data inside Apex — CSV → JSON, XML → SObject list, JSON → flattened CSV, or schema-mapping a third-party payload to a Salesforce model — and the existing options (`JSON.deserialize`, `Dom.Document`, hand-written loops) are getting unwieldy. Triggers: 'apex transform csv json xml without external library', 'system.dataweave script', 'salesforce native dataweave apex execute', 'transform xml to sobject apex no mulesoft', 'json reshape salesforce apex script'. NOT for MuleSoft Anypoint DataWeave running off-platform (use mulesoft-anypoint-architecture), NOT for Apex JSON serialization basics (use apex-json-serialization), NOT for Bulk API CSV ingest (use bulk-api-2-patterns).

flow-invocable-from-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Author @InvocableMethod Apex classes that Flow can call as Actions. Design the input / output variable contract, bulk semantics (one list in, one list out), null handling, and error surfacing. Also covers the inverse direction: calling a flow from Apex via Flow.Interview. NOT for general Apex authoring (use apex-service-selector-domain). NOT for REST-exposed Apex (use apex-rest-resource-patterns).

flow-apex-defined-types

8
from PranavNagrecha/AwesomeSalesforceSkills

Design and use Apex-Defined Types as Flow variables for structured non-sObject data (HTTP callout payloads, External Service responses, complex configuration). Trigger keywords: apex-defined type, flow variable, @AuraEnabled class, flow http callout response. Does NOT cover building HTTP Callout Actions themselves, External Services schema, or raw Apex invocable methods.

scheduled-apex-failure-detection-and-monitoring

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when nightly batch / scheduled Apex jobs are failing without anyone noticing — covers why uncaught exceptions in `execute()` go to the debug log instead of email, how to query `AsyncApexJob` for `Status`, `NumberOfErrors`, and `ExtendedStatus`, when to implement `Database.RaisesPlatformEvents` so the platform publishes `BatchApexErrorEvent` on uncaught failures, how to subscribe to that event with an Apex trigger and notify operators, and how to layer a custom watcher schedule on top so silent-failure modes (job that never started, scheduled class deleted, queue stuck on `Queued`) still surface. Triggers: 'nightly batch failed at 2am with no notification', 'how do we know if a scheduled apex job is failing', 'BatchApexErrorEvent vs custom retry logic', 'Setup Apex Jobs only shows last 7 days, where else can I look', 'job is stuck in queued status nobody noticed for a week'. NOT for general Apex exception handling patterns (use apex/apex-exception-handling-and-logging), NOT for Batch Apex authoring or chunking strategy (use apex/batch-apex-design), NOT for Setup → Apex Jobs UI walkthrough as an admin task (use admin/batch-job-scheduling-and-monitoring), NOT for retry logic itself (use apex/scheduled-apex-retry-patterns once authored).

platform-events-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when publishing or subscribing to Salesforce Platform Events from Apex, comparing Platform Events with Change Data Capture, or designing event-triggered error handling and monitoring. Triggers: 'EventBus.publish', 'platform event trigger', 'CDC vs Platform Events', 'replay ID', 'high-volume event'. NOT for Flow-only publish/subscribe automation.

health-cloud-apex-extensions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when extending Health Cloud via Apex: implementing HealthCloudGA managed-package interfaces, automating care plan lifecycle hooks, processing referrals using Industries Common Components invocable actions, or enforcing HIPAA-compliant logging governance for clinical Apex code. Trigger keywords: CarePlanProcessorCallback, HealthCloudGA namespace, ReferralRequest, ReferralResponse, care plan invocable actions, clinical Apex extension, Health Cloud Apex API. NOT for standard Apex triggers or generic Apex development unrelated to Health Cloud managed-package extension points.

fsl-apex-extensions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when writing Apex that calls Field Service Lightning scheduling APIs — AppointmentBookingService, ScheduleService, GradeSlotsService, or OAAS — to book, schedule, grade, or optimize service appointments programmatically. Trigger keywords: FSL Apex namespace, GetSlots, schedule service appointment via code, appointment booking API, FSL optimization API. NOT for standard Apex patterns unrelated to FSL, admin-level scheduling policy configuration, or declarative FSL scheduling.

fsc-apex-extensions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when extending Financial Services Cloud (FSC) behavior through Apex: customizing financial rollup recalculation, disabling built-in FSC triggers to write custom trigger logic, implementing Compliant Data Sharing (CDS) participant/role integrations, or building custom FSC action handlers. NOT for standard Apex unrelated to the FSC managed package, standard Salesforce sharing rules, or configuring FSC rollups through the Admin UI — use the admin/financial-account-setup skill for declarative rollup setup.

entitlement-apex-hooks

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when writing Apex triggers or classes that interact with CaseMilestone records — completing milestones, detecting violations, or reacting to SLA state changes. Trigger keywords: CaseMilestone trigger, auto-complete milestone Apex, milestone violation polling, CompletionDate write pattern. NOT for entitlement process admin setup, milestone configuration in Setup UI, or Flow-based milestone actions.

dynamic-apex

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building or reviewing code that constructs SOQL/SOSL at runtime, inspects schema metadata via Schema.describe methods, accesses fields dynamically on sObjects, or performs runtime type inspection. Triggers: 'Database.query', 'Schema.getGlobalDescribe', 'Schema.describeSObjects', 'dynamic field access', 'SObjectType', 'DescribeFieldResult'. NOT for static SOQL queries or query performance tuning — use soql-fundamentals or soql-query-optimization.