← Back to TutorialsAL DEVELOPMENT

JSON Handling in Business Central AL: Complete Guide

Dynexal • Beginner to Intermediate • 15 min read

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 you will learn: JsonObject, JsonArray, JsonToken, JsonValue, parsing JSON, reading nested data, creating JSON requests, looping arrays, JPath selection, error handling and real-world API patterns.

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.

Easy way to remember: Object = properties, Array = collection, Token = any JSON node, Value = primitive value.

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;
Production note: the example URL is intentionally illustrative. In a real integration, validate the endpoint, authentication, permissions, response status and JSON contract before processing business data.

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

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.

← Explore all Dynexal tutorials