Using Dyalog's ⎕JSON to Bridge APL Data and Web Services
Learn how Dyalog's built-in ⎕JSON maps APL namespaces and vectors to JSON objects and arrays, with practical examples and version-sensitive pitfalls.
23 Oct 2025, 10:25 UTC

The Integration Problem
When a Dyalog APL application needs to call a REST API or accept a webhook, the payload arrives as JSON text. You could pull in an external parser, but Dyalog ships with a built-in system function, ⎕JSON, that handles both directions. The question is how to use it without letting JSON's flexible shape leak into your APL workspace in ways that break downstream logic.
The short answer: treat ⎕JSON as an explicit boundary tool. Model payloads as namespaces, serialise them with dyadic ⎕JSON, and parse responses with monadic ⎕JSON. Respect the shape rules, and you can keep integration code small and testable.
Parsing Inbound JSON with Monadic ⎕JSON
Monadic ⎕JSON takes a character vector of JSON text and returns APL data. The mapping is predictable:
- JSON objects become Dyalog namespaces.
- JSON arrays become nested APL vectors.
- JSON scalars become native APL types (numbers, character vectors for strings).
- JSON
nullbecomes⎕NULL.
Because ⎕NULL is not a regular array, it can propagate unexpectedly through expressions. If a field might be absent or null, check for it explicitly before doing arithmetic or string operations.
Worked Example: Parsing a Configuration Object
Suppose an endpoint returns this JSON:
{"service":"inventory","timeout":30,"tags":["urgent","batch"],"notes":null}
In a Dyalog session, parse it:
config ← ⎕JSON '{"service":"inventory","timeout":30,"tags":["urgent","batch"],"notes":null}'
Inspect the result. config is a namespace. Use ⎕NC to confirm it is a namespace and ⎕NL 2 to list the names it contains:
⎕NC 'config'
⎕NL 2
Access fields with dot notation: config.service returns the character vector inventory, and config.timeout returns the scalar 30. The array tags becomes a nested vector, and notes is ⎕NULL.
Serialising Outbound Payloads with Dyadic ⎕JSON
Dyadic ⎕JSON converts APL data to JSON text. The left argument is the data; the right argument controls formatting such as compact versus indented output. The mapping mirrors parsing:
- Namespaces become JSON objects.
- Vectors become JSON arrays.
- Character vectors become JSON strings.
A practical pattern is to build a namespace with ⎕NS, assign fields, and serialise it. This keeps the boundary explicit: you decide exactly which fields exist and what they contain.
Worked Example: Building and Serialising a Payload
Create a namespace and populate it:
payload ← ⎕NS ''
payload.id ← 1001
payload.status ← 'active'
payload.quantities ← 5 10 15
payload.metadata ← ⎕NS ''
payload.metadata.region ← 'eu-west'
Serialise with dyadic ⎕JSON. The exact right-argument syntax for formatting options depends on your Dyalog version; consult the documentation for your installed release:
json ← ⎕JSON payload
The result is a character vector containing JSON text. Because payload.metadata is a namespace, it appears as a nested JSON object. The vector quantities becomes a JSON array.
The Shape-Fidelity Trade-off
The central limitation is that JSON has no concept of an APL matrix. When you serialise a matrix, ⎕JSON produces an array of arrays. There is no shape metadata, so the consumer sees rows and columns but cannot distinguish a 2-by-3 matrix from a nested vector of two three-element vectors. If your consumer expects a specific rank, document it or flatten the data before sending.
Key order is the other side of the same coin. JSON objects are unordered by specification. When you parse a JSON object into a namespace, the order of names returned by ⎕NL is not guaranteed to match the source text, and it may not be alphabetical. Any consumer that relies on positional field order—human or machine—is fragile.
Version Sensitivity and Verification
The right-argument options for dyadic ⎕JSON have evolved across Dyalog releases. What worked in an older version may be deprecated or behave differently in a newer one. Numeric precision is another moving target: APL's internal representation and a JSON consumer's parser may disagree on high-precision or special float values. Before deploying, validate against your specific Dyalog version.
Round-Trip Check
A practical verification is to serialise a payload, parse it back, and compare structures. Use ≡ for deep structural equality where appropriate:
roundTripped ← ⎕JSON json
(payload ≡ roundTripped)
If the structures match exactly, ≡ returns 1. If it returns 0, inspect the differences. A common cause is ⎕NULL: if a field was null in the original JSON, the round-tripped namespace may differ from a namespace you built manually. For numeric fields, compare with a tolerance rather than exact equality if high-precision values are involved.
Practical Checklist
- Model every API payload as a namespace with explicit fields.
- Parse responses with monadic
⎕JSONand check for⎕NULLbefore use. - Serialise with dyadic
⎕JSONand confirm the right-argument options in your Dyalog documentation. - Round-trip test every payload type during development.
- Never assume JSON key order or matrix shape survives the boundary.
Dyalog's ⎕JSON removes the need for external parsers in many integration tasks, but it is not a lossless bridge. Treat the conversion point as a deliberate design boundary, verify against your installed version, and the rest of your APL code can stay array-native.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.