JSON Handling in Business Central AL: Complete Guide
JSON is one of the most common formats used when Business Central exchanges data with REST APIs, websites, e-commerce platforms and middleware. In AL, the JSON data types give you a structured way to read, create, update and navigate JSON without treating the payload as plain text.
What is JSON?
JSON (JavaScript Object Notation) is a lightweight data format built from objects, arrays and primitive values. A typical API response might look like this:
{
"id": "CUST-1001",
"name": "Dynexal Demo Customer",
"active": true,
"orders": [
{ "number": "SO-1001", "amount": 1250.50 },
{ "number": "SO-1002", "amount": 875.00 }
]
}
The object contains properties such as id and name, while orders contains an array of objects. Understanding this structure is the key to working with JSON in AL.
JSON data types in AL
Business Central provides four core JSON data types: JsonObject, JsonArray, JsonToken and JsonValue. These are the main AL types for working with well-formed JSON data.
- JsonObject: represents a JSON object containing key/value properties.
- JsonArray: represents an ordered JSON array.
- JsonToken: can represent any JSON value and is useful when the exact type is not known yet.
- JsonValue: represents a fundamental JSON value such as text, number, Boolean or null.
Reading JSON into a JsonObject
If the root of the response is a JSON object, JsonObject.ReadFrom(Text) can parse the text into a JsonObject. The method also has an optional Boolean result and can fail when the JSON is malformed.
procedure ReadCustomerJson(JsonText: Text)
var
CustomerJson: JsonObject;
begin
if not CustomerJson.ReadFrom(JsonText) then
Error('Invalid JSON response.');
Message(CustomerJson.GetText('name'));
end;
Using the Boolean result is useful when JSON comes from an external system because a malformed response should be handled deliberately instead of causing an unexpected runtime error.
Reading simple properties
For known text properties, JsonObject.GetText can retrieve the value directly.
CustomerName := CustomerJson.GetText('name');
For more control, use Get with a JsonToken:
var
Token: JsonToken;
begin
if CustomerJson.Get('name', Token) then
Message(Token.AsValue().AsText());
end;
JsonObject.Get retrieves a property into a JsonToken and can return a Boolean when the property exists.
JsonToken and JsonValue
A JsonToken is especially useful when an API can return different JSON shapes or when a property may contain an object, array or primitive value. You can convert a token into a more specific type when you know its structure.
var
Token: JsonToken;
Value: JsonValue;
CustomerName: Text;
begin
CustomerJson.Get('name', Token);
Value := Token.AsValue();
CustomerName := Value.AsText();
end;
JsonToken.AsObject() converts a token into JsonObject, while JsonToken.AsValue() converts it into JsonValue. JsonValue provides conversion methods such as AsText, AsDecimal and AsBoolean.
Reading JSON arrays
When a response contains an array, use JsonArray. Array indexes in AL are zero-based, so the first element is index 0.
var
Orders: JsonArray;
OrderToken: JsonToken;
OrderObject: JsonObject;
I: Integer;
begin
Orders := CustomerJson.GetArray('orders');
for I := 0 to Orders.Count() - 1 do begin
Orders.Get(I, OrderToken);
OrderObject := OrderToken.AsObject();
Message(OrderObject.GetText('number'));
end;
end;
This pattern is common when an API returns a collection of customers, orders, products, inventory records or other entities.
Creating JSON in AL
JSON is not only for reading API responses. You will often need to create a request body for a POST or PATCH operation. JsonObject supports adding properties including text, Boolean, JsonObject and JsonArray values.
var
RequestJson: JsonObject;
RequestBody: Text;
begin
RequestJson.Add('customerId', 'CUST-1001');
RequestJson.Add('name', 'Dynexal Demo Customer');
RequestJson.Add('active', true);
RequestJson.WriteTo(RequestBody);
end;
The resulting text can then be placed into an HttpContent object and sent with HttpClient.
Creating a JSON array
You can create a JsonArray and add JSON objects to it. This is useful when an external API expects multiple lines in one request.
var
Lines: JsonArray;
Line: JsonObject;
RequestJson: JsonObject;
RequestBody: Text;
begin
Line.Add('itemNo', '1000');
Line.Add('quantity', 2);
Lines.Add(Line);
Clear(Line);
Line.Add('itemNo', '2000');
Line.Add('quantity', 5);
Lines.Add(Line);
RequestJson.Add('lines', Lines);
RequestJson.WriteTo(RequestBody);
end;
Working with nested JSON
Nested objects can be read by getting a JsonToken and converting it to JsonObject.
var
AddressToken: JsonToken;
Address: JsonObject;
begin
if CustomerJson.Get('address', AddressToken) then begin
if AddressToken.IsObject() then begin
Address := AddressToken.AsObject();
Message(Address.GetText('city'));
end;
end;
end;
This is safer than assuming every response always contains every nested property. External APIs can change or omit optional fields.
Using JPath with SelectToken
For deeper or conditional JSON navigation, AL supports JPath through SelectToken. This method selects a JsonToken using a JPath expression.
var
SalaryToken: JsonToken;
Query: Text;
begin
Query := '$.company.employees[?(@.id==''John'')].salary';
if CompanyJson.SelectToken(Query, SalaryToken) then
Message('%1', SalaryToken.AsValue().AsDecimal());
end;
Use JPath when direct Get calls become difficult to maintain, especially with deeply nested responses.
Using JSON with HttpClient
JSON and HttpClient are frequently used together in Business Central integrations. The HTTP types provide the transport layer, while JSON types help you interpret the request and response bodies.
procedure CallExternalApi()
var
Client: HttpClient;
Response: HttpResponseMessage;
ResponseText: Text;
ResponseJson: JsonObject;
Url: Text;
begin
Url := 'https://api.example.com/customers/CUST-1001';
if not Client.Get(Url, Response) then
Error('The HTTP request could not be sent.');
if not Response.IsSuccessStatusCode() then
Error('API returned status %1.', Response.HttpStatusCode());
Response.Content().ReadAs(ResponseText);
if not ResponseJson.ReadFrom(ResponseText) then
Error('The API returned invalid JSON.');
Message('Customer: %1', ResponseJson.GetText('name'));
end;
Handling optional and missing properties
A common integration problem is assuming that every field exists. APIs may omit optional properties or return null values. Use Boolean-returning methods where appropriate and check the token/value before converting it.
var
Token: JsonToken;
begin
if CustomerJson.Get('phone', Token) then begin
if not Token.IsValue() then
exit;
Message(Token.AsValue().AsText());
end;
end;
For simple text properties, you can also use the optional default behavior of methods such as GetText when that matches your integration requirements.
Common JSON errors in Business Central
Malformed JSON
If ReadFrom cannot parse the payload, inspect the raw response. Common causes include missing quotes, invalid commas, truncated responses or HTML error pages returned instead of JSON.
Property not found
Calling a getter for a property that does not exist can fail. Use the Boolean form of Get when a property is optional.
Wrong JSON type
A property that you expect to be text might actually be a number, Boolean, object or null. Check the API contract before calling conversion methods such as AsText or AsDecimal.
Array index errors
JsonArray is zero-based. Check Count() before accessing an index and do not assume that a response always contains at least one item.
Unexpected API response
Always check the HTTP status code before parsing a response. A 401, 403, 404 or 500 response may contain a completely different JSON structure from the successful response.
JSON best practices for AL developers
- Validate HTTP status codes before parsing response bodies.
- Use JsonObject and JsonArray instead of manually concatenating large JSON strings.
- Use Boolean-returning methods when a property may be missing or the payload may be invalid.
- Keep external API contracts documented and version-aware.
- Do not log access tokens, passwords, API keys or other secrets.
- Keep JSON parsing separate from core business logic where practical.
- Use reusable procedures or codeunits for repeated integration patterns.
- Test empty arrays, missing properties, null values, malformed JSON and unexpected HTTP status codes.
- Use JPath selectively for complex nested data rather than making every simple lookup complicated.
- Keep sample payloads and automated tests for important integrations.
Real-world Business Central JSON flow
External API
|
| JSON response
v
HttpClient
|
| ResponseText
v
JsonObject / JsonArray
|
| Validate + extract values
v
AL Business Logic
|
v
Business Central Tables
This separation makes integration code easier to understand: HTTP handles communication, JSON types handle structure, and AL business logic decides what the data means for Business Central.
What should you learn next?
HttpClient in Business Central AL — learn how to call external REST APIs.
Business Central API Integration — understand API pages, endpoints, CRUD and authentication concepts.
Codeunits in Business Central — organize reusable integration and business logic.
AL Event Subscribers — react to Business Central events without modifying base application code.
Shopify and Business Central Integration — see how JSON, APIs and synchronization fit into an e-commerce integration.