Working with JSON
Since AL programming is avaible it is pretty easy to work with json.
AL supports us with JsonObject, JsonArray, JsonValue and JsonToken, which can be one of the other three types.
Let us check some code examples, how you can consume and work with JSON data.
We receiving following JSON array and need to import it into customer table:
[
{
no: "00001",
name: "Dummy Customer 1"
},
{
no: "00002",
name: "Dummy Customer 2"
}
]
The AL code would look like this:
procedure ImportCustomerJsonArray(CustomerJsonArray: JsonArray)
var
CustomerJsonObject: JsonObject;
JsonTokenHelper: JsonToken;
begin
foreach JsonTokenHelper in CustomerJsonArray do begin
CustomerJsonObject := JsonTokenHelper.AsObject();
ImportCustomerJson(CustomerJsonObject);
end;
end;
procedure ImportCustomerJson(CustomerJsonObject: JsonObject)
var
Customer: Record Customer;
JsonTokenHelper: JsonToken;
No: Code[20];
begin
CustomerJsonObject.Get('no', JsonTokenHelper);
No := JsonTokenHelper.AsValue().AsText();
if not Customer.Get(No) then begin
Customer.Init();
Customer."No." := No;
Customer.Insert(true);
end;
CustomerJsonObject.Get('name', JsonTokenHelper);
Customer.Name := JsonTokenHelper.AsValue().AsText();
// ...
Customer.Modify(true);
end;
As you can see, not that hard!
But what happens if we have a more nested JSON?
{
no: "00001",
name: "Dummy Customer 1",
address: {
street: "Dummy Street 1",
zipcode: "12345",
city: "Berlin"
}
}
Do you know the power of “selectToken“? You can use JPath there (if you dont know what it is: here)
// ...
CustomerJsonObject.SelectToken('$.adress.street', JsonTokenHelper);
Customer.Address := JsonTokenHelper.AsValue().AsText();
// ...
Let us be a little bit more complicated:
{
no: "00001",
name: "Dummy Customer 1",
address: [
{
type: "BILLING"
street: "Dummy Street 1",
zipcode: "12345",
city: "Berlin"
},
{
type: "SHIPPING"
street: "Dummy Street 1",
zipcode: "99999",
city: "SomewhereElse"
}
]
}
And the AL code:
// ...
CustomerJsonObject.SelectToken('$.adress[?(@.type==''BILLING'')].street', JsonTokenHelper);
Customer.Address := JsonTokenHelper.AsValue().AsText();
// ...
Still easy! You just need to understand how JPath works.
It`s time to make the code a bit more clean
In all cases we fill our “JsonTokenHelper” and after get the value as text. Lets create a function for it.
procedure GetValueAsText(JPath: Text; JToken: JsonToken) ReturnValue: Text
var
SelectToken: JsonToken;
begin
JToken.SelectToken(JPath, SelectToken);
ReturnValue := SelectToken.AsValue().AsText();
end;
And here how we can use it:
procedure ImportCustomerJson(CustomerJsonObject: JsonObject)
var
Customer: Record Customer;
JsonTokenHelper: JsonToken;
No: Code[20];
begin
No := GetValueAsText('$.no', CustomerJsonObject.AsToken());
if not Customer.Get(No) then begin
Customer.Init();
Customer."No." := No;
Customer.Insert(true);
end;
Customer.Name := GetValueAsText('$.name', CustomerJsonObject.AsToken());
Customer.Address := GetValueAsText('$.adress[?(@.type==''BILLING'')].street', CustomerJsonObject.AsToken());
Customer.Modify(true);
end;
Our code looks much cleaner now.
Let me provide you a “JSON Helper” codeunit.
codeunit 50000 "JSON Helper"
{
procedure GetValueAsText(Path: Text; JToken: JsonToken) ReturnValue: Text
var
SelectToken: JsonToken;
begin
if JToken.SelectToken(Path, SelectToken) then
if not SelectToken.AsValue().IsNull() then
ReturnValue := SelectToken.AsValue().AsText().Replace('\"', '"');
end;
procedure GetValueAsBoolean(Path: Text; JToken: JsonToken) ReturnValue: Boolean
var
SelectToken: JsonToken;
begin
if JToken.SelectToken(Path, SelectToken) then
if not SelectToken.AsValue().IsNull() then
ReturnValue := SelectToken.AsValue().AsBoolean()
end;
procedure GetValueAsInt(Path: Text; JToken: JsonToken) ReturnValue: Integer
var
SelectToken: JsonToken;
begin
if JToken.SelectToken(Path, SelectToken) then
if not SelectToken.AsValue().IsNull() then
ReturnValue := SelectToken.AsValue().AsInteger()
end;
// ...
}
>> see complete code here <<
This codeunit contains functions for different datatypes, it takes care of escaping, NULL values and broken JSON values.
Is it helpfull? Is something unclear?
1 comment so far