Interacting with a REST API to Retrieve JSON Data
Now that you’re familiar with basic HTTP interactions using DBL, let’s delve into something more complex: calling a REST API and processing JSON data. We’ll use jsonplaceholder.typicode.com
for this purpose, a fake online REST API often used for testing and prototyping. Specifically, we’ll retrieve a list of posts and then process the JSON response using the System.Text.Json.JsonDocument
API in DBL.
Imports
First, make sure you have included the necessary namespace:
import System.Text.Json
Fetching data from a REST API
We’ll start by creating a function to make a GET request to the /posts
endpoint of JSONPlaceholder, which returns a list of sample blog posts in JSON format.
function GetPosts, @string
record
response, @string
errtxt, @string
status, int
responseHeaders, [#]string
proc
status = %http_get("https://jsonplaceholder.typicode.com/posts", 5, response, errtxt, ^NULL, responseHeaders, , , , , , , "1.0")
freturn response
endfunction
This code sends a GET request to the /posts
endpoint and prints the JSON response.
Processing JSON data
Now, let’s process the JSON data we received. We’ll call our function and use System.Text.Json.JsonDocument
for parsing the JSON string.
record
jsonDoc, @JsonDocument
jsonElement, @JsonElement
post, @string
arrayIterator, int
arrayLength, int
proc
jsonDoc = JsonDocument.Parse(%GetPosts())
arrayLength = jsonDoc.RootElement.GetArrayLength()
for arrayIterator from 0 thru arrayLength-1 by 1
begin
jsonElement = jsonDoc.RootElement[arrayIterator]
post = jsonElement.GetProperty("title").GetString()
Console.WriteLine("Post Title: " + post)
end
In this snippet, we parse the JSON response into a JsonDocument
. Then, we iterate over the array of posts, extracting and printing the title of each post. It’s important to note that in Traditional DBL, you must keep the jsonDoc variable in scope for the lifetime of the jsonElement variable. This is because the jsonElement variable is a reference to the jsonDoc variable. If you don’t keep the jsonDoc variable in scope, the jsonElement variable will be invalid.
There’s a lot more you can do with the JSON API, and typicode.com has a lot more endpoints you can play with. If you’re running .NET, you can look at the Microsoft documentation for the System.Text.Json.JsonDocument API, Microsoft documentation. If you’re running Traditional DBL, you can look at the Synergex documentation for the Json.JsonDocument class, Synergex documentation.
Writing data with Utf8JsonWriter
Utf8JsonWriter is borrowed from .NET and provides a high-performance way to write JSON data. Because Traditional DBL doesn’t have streams, we’ll write a new program and use System.StringBuilder as our output target and then fling our JSON data at httpbin.org to show it off.
Imports
First, make sure you have included the necessary namespaces:
import System.Text
import System.Text.Json
Initializing Utf8JsonWriter
Utf8JsonWriter writes JSON data to an output buffer. In this example, we’ll use a stream as our output buffer.
main
record
outputBuffer, @StringBuilder
jsonWriter, @Utf8JsonWriter
proc
outputBuffer = new StringBuilder()
jsonWriter = Utf8JsonWriter.CreateUtf8JsonWriter(outputBuffer)
endmain
This code initializes a Utf8JsonWriter that writes to our StringBuilder buffer.
Writing JSON data
Let’s create a simple JSON object with a few properties.
In order to start the JSON object, we need to call WriteStartObject()
.
jsonWriter.WriteStartObject()
This begins our JSON object. Now we can add some properties to the JSON object.
jsonWriter.WriteString("name", "John Doe")
jsonWriter.WriteNumber("age", 30)
jsonWriter.WriteBoolean("isMember", true)
These lines add a string, a number, and a Boolean property to the JSON object. We can now conclude the JSON object writing.
jsonWriter.WriteEndObject()
It’s important to flush the Utf8JsonWriter to ensure all data is written to the stream and then close it.
jsonWriter.Flush()
Doing something with the data
Now that we’ve written some JSON data to our StringBuilder buffer, let’s do something with it. We’ll send it to the httpbin.org
Anything endpoint to see what we’ve written.
main
record
outputBuffer, @StringBuilder
jsonWriter, @Utf8JsonWriter
response, @string
request, @string
errtxt, @string
status, int
responseHeaders, [#]string
requestHeaders, [#]string
proc
outputBuffer = new StringBuilder()
jsonWriter = Utf8JsonWriter.CreateUtf8JsonWriter(outputBuffer)
jsonWriter.WriteStartObject()
jsonWriter.WriteString("name", "John Doe")
jsonWriter.WriteNumber("age", 30)
jsonWriter.WriteBoolean("isMember", true)
jsonWriter.WriteEndObject()
jsonWriter.Flush()
request = outputBuffer.ToString()
requestHeaders = new string[#] { "Content-Type: application/json" }
status = %http_post("https://httpbin.org/anything",5,request, response,errtxt,requestHeaders,responseHeaders,,,,,,,"1.0")
Console.WriteLine(response)
endmain
The response should look something like this:
{
"args": {},
"data": "{\"name\":\"John Doe\",\"age\":30,\"isMember\":true}",
"files": {},
"form": {},
"headers": {
"Content-Length": "44",
"Content-Type": "application/json",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-657937b8-492f8fc147c17845481295b9"
},
"json": {
"age": 30,
"isMember": true,
"name": "John Doe"
},
"method": "POST",
"origin": "10.1.1.1",
"url": "https://httpbin.org/anything"
}
There are a few things to note here. First, the data
property is a string representation of the JSON data we sent. Second, the json
property is a JSON object representation of the JSON data we sent. Third, the headers
property contains the headers we sent with our request. Finally, the method
property contains the HTTP method we used. It would be an interesting exercise to parse this response and extract something useful using what you’ve learned so far about JSON parsing in DBL. When you’re done with that, it’s time to up our data structure game and learn about complex types.