Get JSON data from external REST services

Completed

Previously, you were shown how a result is retrieved as text; however, that was actually a JSON document. Because AL has built-in support for JSON types, you can modify your solution to work with a JSON document.

Before you can work with a JSON document, you first need to parse the downloaded text value to a JsonToken. The JsonToken data type is the base class for all other JSON data types. Therefore, you will use the ReadFrom function on the JsonToken data type to read and parse the input as a JSON document. This function returns a Boolean value, indicating that the input was a valid JSON structure.

The subsequent code example shows how the value of the ResponseString variable is parsed as a JsonToken. Data has been retrieved from the following.

https://jsonplaceholder.typicode.com/users/<number>

The JSON response for a user with number five is illustrated in the following code sample.

{
  "id": 5,
  "name": "Chelsey Dietrich",
  "username": "Kamren",
  "email": "Lucio_Hettinger@annie.ca",
  "address": {
    "street": "Skiles Walks",
    "suite": "Suite 351",
    "city": "Roscoeview",
    "zipcode": "33263",
    "geo": {
      "lat": "-31.8129",
      "lng": "62.5342"
    }
  },
  "phone": "(254)954-1289",
  "website": "demarco.info",
  "company": {
    "name": "Keebler LLC",
    "catchPhrase": "User-centric fault-tolerant solution",
    "bs": "revolutionize end-to-end systems"
  }
}

The ReadFrom function is used to parse the response text into a JSON document. As shown in the previous response example, the JSON document is not an array but a JsonObject with some keys and values. Therefore, you would first test that your JsonToken is a JsonObject and then convert it with the AsObject function to a JsonObject data type. In a JsonObject data type, you can use the Get function to retrieve a value based on the key. In this example, you will get the value for the name key, which again results in a new JsonToken. As shown in the previous response example, the value for the name key is the lowest level in the JSON object, which is called a JsonValue data type.

This JsonToken will be converted into a JsonValue. The content is of type Text, so you need to convert the JsonValue as a text value with the AsText function.

procedure GetUserInformation(UserNumber: Integer)
var
    Client: HttpClient;
    ResponseMessage: HttpResponseMessage;
    ResponseString: Text;
    Jtoken: JsonToken;
    Jtoken2: JsonToken;
    JObject: JsonObject;
begin
    if not Client.Get(StrSubstNo('https://jsonplaceholder.typicode.com/users/%1',
                      UserNumber), ResponseMessage) then
        Error('The call to the web service failed.');

    if not ResponseMessage.IsSuccessStatusCode() then
        Error('The web service returned an error message:\\' +
              'Status code: ' + Format(ResponseMessage.HttpStatusCode()) +
              'Description: ' + ResponseMessage.ReasonPhrase());

    ResponseMessage.Content().ReadAs(ResponseString);

    if not Jtoken.ReadFrom(ResponseString) then
        Error('Invalid JSON document.');

    if not Jtoken.IsObject() then
        Error('Expected a JSON object.');

    JObject := Jtoken.AsObject();

    if not JObject.Get('name', Jtoken2) then
        Error('Value for key name not found.');

    if not Jtoken2.IsValue then 
        Error('Expected a JSON value.');      

    Message(Jtoken2.AsValue().AsText());
end;

The JSON and HTTP data types allow you to concatenate multiple functions in one line of code. Instead of defining an extra variable with a JsonValue data type and assigning the Jtoken.AsValue to that variable, you can complete this action in one implementation.

var
    Jtoken: JsonToken;
    Jvalue: JsonValue;
begin  
    Jvalue := Jtoken.AsValue();
    Message(Jvalue.AsText());

    // You can execute this in one line
    Message(Jtoken.AsValue().AsText());
end;

The following example shows how you can create your own JsonObject to later send it by using the HttpClient to a REST service. You can use the Add function on the JsonObject data type to add new key/value pairs. Using the WriteTo function results in the JsonObject being serialized in a text value.

procedure CreatePost()
var
    Client: HttpClient;
    Content: HttpContent;
    ResponseMessage: HttpResponseMessage;
    ResponseString: Text;
    JObject: JsonObject;
    JsonText: Text;
begin 

    JObject.Add('userId', 2);
    JObject.Add('id', 101);
    JObject.Add('title', 'Microsoft Dynamics 365 Business Central Post Test');
    JObject.Add('body', 'This is a MS Dynamics 365 Business Central Post Test');
    JObject.WriteTo(JsonText);

    Content.WriteFrom(JsonText);

    if not Client.Post('https://jsonplaceholder.typicode.com/posts', Content, 
                       ResponseMessage) then
        Error('The call to the web service failed.');

    if not ResponseMessage.IsSuccessStatusCode() then
        Error('The web service returned an error message:\\' +
                'Status code: ' + Format(ResponseMessage.HttpStatusCode()) +
                'Description: ' + ResponseMessage.ReasonPhrase());

    ResponseMessage.Content().ReadAs(ResponseString);

    Message(ResponseString);
end;