How to consume REST API Url in Microsoft D365 Business Central - Example Getting data from JsonPlaceholder API

Hi folks,

In this article I will share all the code that I have been used to fetch User information from JsonPlaceholder Rest API and stored the JSON response in D365 Business Central tables.

Let's see the result first: 

For this demo I have created the 5 objects and organized in structure like below screenshot:

Note: Not including 50102_UserCard.Page.al in this article.

You can check the response from the JsonPlaceholder API from URL: https://jsonplaceholder.typicode.com/users

So what I am going to do here to fetch and store this User information that I am getting from the above URL, I will first create a table object that will store all information that available in code and value pair.

As the API contains following response:

Based on the API Response, Let's create a TABLE

------------------------
table 50100 JP_Users
{
    Caption = 'Json Placeholder Users';

    DataClassification = ToBeClassified;

    fields
    {
        field(1; UUID; Integer)
        {
            DataClassification = ToBeClassified;
            AutoIncrement = true;
        }
        field(2; id; Integer) { DataClassification = ToBeClassified; }
        field(3; name; Text[50]){ DataClassification = ToBeClassified; }
        field(4; username; Text[30]){ DataClassification = ToBeClassified; }
        field(5; email; Text[30]){ DataClassification = ToBeClassified; }
        field(6; street; Text[50]){ DataClassification = ToBeClassified; }
        field(7; suite; Text[50]){ DataClassification = ToBeClassified; }
        field(8; city; Text[50]){ DataClassification = ToBeClassified; }
        field(9; zipcode; Text[50]){ DataClassification = ToBeClassified; }
        field(10; lat; Text[250]){ DataClassification = ToBeClassified; }
        field(11; lng; Text[250]){ DataClassification = ToBeClassified; }
        field(12; phone; Text[30])
        {
            DataClassification = ToBeClassified;
            ExtendedDatatype = PhoneNo;
        }
        field(13; website; Text[150])
        {
            DataClassification = ToBeClassified;
            ExtendedDatatype = URL;
        }
        field(14; companyName; Text[100]){ DataClassification = ToBeClassified; }
        field(15; companyCatchPhrase; Text[250]){ DataClassification = ToBeClassified; }
        field(16; companyBS; Text[250]){ DataClassification = ToBeClassified; }
    }

    keys
    {
        key(PK; UUID)
        {
            Clustered = true;
        }
    }
}



 
 

Create 3 different codeunits:
50146 JSON_Methods
50100 API_RequestHandlerCodeunit
50101 API_ResponseHandlerCodeunit

Codeunit 1: I will use this codeunit for to read values from JSON Object

---------------------
codeunit 50146 JSON_Methods
{
    trigger OnRun()
    begin
    end;

    // GetJsonValue is use to get the value format and helpful to convert in any data type 
    procedure GetJsonValue(var json_Object: JsonObject; Property: Text; var json_Value: JsonValue): Boolean
    var
        json_Token: JsonToken;
    begin
        if not json_Object.Get(Property, json_Token) then
            exit;
        json_Value := json_Token.AsValue();
        exit(true);
    end;


    // Work for Text Response
    procedure GetJsonValueAsText(var json_Object: JsonObject; Property: Text) Value: Text
    var
        json_Value: JsonValue;
    begin
        if not GetJsonValue(json_Object, Property, json_Value) then
            exit;
        Value := json_Value.AsText;
    end;

    procedure GetJsonValueAsBoolean(var json_Object: JsonObject; Property: Text) Value: Boolean
    var
        json_Value: JsonValue;
    begin
        if not GetJsonValue(json_Object, Property, json_Value) then
            exit;
        Value := json_Value.AsBoolean();
    end;

    procedure GetJsonValueAsInteger(var json_Object: JsonObject; Property: Text) Value: Integer
    var
        json_Value: JsonValue;
    begin
        if not GetJsonValue(json_Object, Property, json_Value) then
            exit;
        Value := json_Value.AsInteger();
    end;

    procedure GetJsonValueAsDecimal(var json_Object: JsonObject; Property: Text) Value: Decimal
    var
        json_Value: JsonValue;
    begin
        if not GetJsonValue(json_Object, Property, json_Value) then
            exit;
        Value := json_Value.AsDecimal();
    end;

    procedure GetJsonToken(json_Object: JsonObject; tokenKey: Text) json_Token: JsonToken;
    begin
        if not json_Object.Get(tokenKey, json_Token) then
            Error('Token not found with key %1', tokenKey);
    end;

    procedure SelectJsonToken(json_object: JsonObject; path: Text) json_Token: JsonToken;
    begin
        if not json_object.SelectToken(path, json_Token) then
            Error('Token not found with path %1', path);
    end;
}

 

 

Codeunit 2: I will use this codeunit for making request 

 
-----------------------
codeunit 50100 API_RequestHandlerCodeunit
{
    trigger OnRun()
    begin
    end;

    procedure GetResponse(requestURL: Text; erroMsg: Text): Text
    var
        httpClient: HttpClient;
        httpResponseMsg: HttpResponseMessage;
        httpRequestMsg: HttpRequestMessage;
        response: Text;
        recWebServiceLog: Record WebServiceLog;
        cuCommon: Codeunit CommonCodeunit;
    begin
        erroMsg := '';
        cuCommon.InsertWebServiceLog('', '', requestURL, recWebServiceLog);
        if not httpClient.Get(requestURL, httpResponseMsg) then begin
            erroMsg := 'The call to webservice is failed';
        end;

        if not httpResponseMsg.IsSuccessStatusCode then begin
            erroMsg += '\The request call returned an error message. \Detail: \Status Code: ' + 
                   Format(httpResponseMsg.HttpStatusCode) + '\Description: ' + httpResponseMsg.ReasonPhrase;
        end;

        httpResponseMsg.Content.ReadAs(response);
        cuCommon.UpdateWebServiceLog(recWebServiceLog);
        exit(response);
    end;
}

 

Codeunit 3: I will use this code unit for handling response

 
-------------------------
codeunit 50101 API_ResponseHandlerCodeunit
{
    trigger OnRun()
    begin
    end;

    procedure UsersInfoFromResponse(response: Text): Boolean
    var
        responseArray: JsonArray;
        json_Token: JsonToken;
        json_Object: JsonObject;
        userInfo_JsonObject: JsonObject;
        i: Integer;
    begin
        //if json_Object.ReadFrom(response) then begin        
        if json_Token.ReadFrom(response) then begin
            if json_Token.IsArray then   // json_Token.IsArray; json_Token.IsObject; json_Token.IsValue;
                responseArray := json_Token.AsArray();
            for i := 0 to responseArray.Count() - 1 do begin
                // Get First Array Result
                responseArray.Get(i, json_Token);
                // Convert JsonToken to JsonObject
                if json_Token.IsObject then begin
                    userInfo_JsonObject := json_Token.AsObject();
                    insertUsersDetail(userInfo_JsonObject);
                end;

            end;
        end;
        //end;
        exit(true);
    end;

    procedure insertUsersDetail(userInfoJsonObject: JsonObject)
    var
        recJPUser: Record JP_Users;
        json_Methods: Codeunit JSON_Methods;
        retJsonValue: JsonValue; // this can be used when getting value from GetJsonValue method
        addressJsonObject: JsonObject;
        addressJsonToken: JsonToken;
        geoJsonObject: JsonObject;
        geoJsonToken: JsonToken;
        companyJsonObject: JsonObject;
        companyJsonToken: JsonToken;
    begin
        recJPUser.Reset();
        recJPUser.Init();
        recJPUser.id := json_Methods.GetJsonToken(userInfoJsonObject, 'id').AsValue().AsInteger();

        recJPUser.id := json_Methods.GetJsonValueAsInteger(userInfoJsonObject, 'id');

        if json_Methods.GetJsonValue(userInfoJsonObject, 'id', retJsonValue) then
            recJPUser.id := retJsonValue.AsInteger();

        recJPUser.name := json_Methods.GetJsonValueAsText(userInfoJsonObject, 'name');

        // With GetJsonValue
        if json_Methods.GetJsonValue(userInfoJsonObject, 'username', retJsonValue) then
            recJPUser.username := retJsonValue.AsText();

        recJPUser.email := json_Methods.GetJsonValueAsText(userInfoJsonObject, 'email');

        // Using separate function GetJsonValueAsText
        // Start: Get Address Details
        if userInfoJsonObject.Get('address', addressJsonToken) then begin
            if addressJsonToken.IsObject then begin
                addressJsonObject := addressJsonToken.AsObject();
                recJPUser.street := json_Methods.GetJsonValueAsText(addressJsonObject, 'street');
                recJPUser.suite := json_Methods.GetJsonValueAsText(addressJsonObject, 'suite');
                recJPUser.city := json_Methods.GetJsonValueAsText(addressJsonObject, 'city');
                recJPUser.zipcode := json_Methods.GetJsonValueAsText(addressJsonObject, 'zipcode');
                // Start: Geo
                if addressJsonObject.Get('geo', geoJsonToken) then begin
                    if geoJsonToken.IsObject then begin
                        geoJsonObject := geoJsonToken.AsObject();
                        recJPUser.lat := json_Methods.GetJsonValueAsText(geoJsonObject, 'lat');
                        recJPUser.lng := json_Methods.GetJsonValueAsText(geoJsonObject, 'lng');
                    end;
                end;
                // Stop: Geo
            end;
        end;
        // Stop: Get Address Details

        recJPUser.phone := json_Methods.GetJsonValueAsText(userInfoJsonObject, 'phone');
        recJPUser.website := json_Methods.GetJsonValueAsText(userInfoJsonObject, 'website');

        // Start: Company Details
        if userInfoJsonObject.Get('company', companyJsonToken) then begin
            if companyJsonToken.IsObject then begin
                companyJsonObject := companyJsonToken.AsObject();
                recJPUser.companyName := json_Methods.GetJsonValueAsText(companyJsonObject, 'name');
                recJPUser.companyCatchPhrase := json_Methods.GetJsonValueAsText(companyJsonObject, 
                  'catchPhrase');
                recJPUser.companyBS := json_Methods.GetJsonValueAsText(companyJsonObject, 'bs');
            end;
        end;
        // Stop: Company Details
        recJPUser.Insert();
    end;
}

 

Finally Create a list page with Action "Get Users From API": 

-----------------------
page 50100 JP_Users
{
    Caption = 'Json Placeholder Users';
    PageType = List;
    ApplicationArea = All;
    UsageCategory = Lists;
    SourceTable = JP_Users;
    CardPageId = "JP User Card";

    layout
    {
        area(Content)
        {
            repeater(GroupName)
            {
                field(UUID; UUID)
                {
                    ApplicationArea = All;
                }
                field(id; id) { ApplicationArea = All; }
                field(name; name) { ApplicationArea = All; }
                field(username; username) { ApplicationArea = All; }
                field(email; email) { ApplicationArea = All; }
                field(street; street) { ApplicationArea = All; }
                field(suite; suite) { ApplicationArea = All; }
                field(city; city) { ApplicationArea = All; }
                field(zipcode; zipcode) { ApplicationArea = All; }
                field(lat; lat) { ApplicationArea = All; }
                field(lng; lng) { ApplicationArea = All; }
                field(phone; phone) { ApplicationArea = All; }
                field(website; website) { ApplicationArea = All; }
                field(companyName; companyName) { ApplicationArea = All; }
                field(companyCatchPhrase; companyCatchPhrase) { ApplicationArea = All; }
                field(companyBS; companyBS) { ApplicationArea = All; }
            }
        }       
    }

    actions
    {
        area(Processing)
        {
            action(GetUsersFromAPI)
            {
                ApplicationArea = All;
                Caption = 'Get Users From API';

                trigger OnAction();
                var
                    apiCodeunit: Codeunit API_RequestHandlerCodeunit;
                    response: Text;
                    errorMsg: Text;
                    apiResponseHandler: Codeunit API_ResponseHandlerCodeunit;
                begin
                    response := apiCodeunit.GetResponse('https://jsonplaceholder.typicode.com/users', errorMsg);
                    if errorMsg <> '' then
                        Error(errorMsg)
                    else
                        Message('Your API Call Response: \' + response);

                    if response <> '' then begin
                        if apiResponseHandler.UsersInfoFromResponse(response) then
                            Message('Records inserted Successfully!');
                    end;                    
                end;
            }
        }
    }
}


 

That's All, Happy Coding!

Stay Tuned!

 

Add comment