World Bank API in C#
by Cyrus Hartwin Gomes
See the World Bank API documentation
These recipe examples were tested on July 25, 2023
Setup#
First, install the CURL and jq package by typing the following command in the terminal:
!sudo apt install curl jq libcurl4-openssl-dev
Then, we set a directory where we want the WorldBank directory for our projects to be created:
!mkdir World_Bank
Finally, we change the directory to the folder we created:
%cd World_Bank
1. Get list of country iso2Codes and names#
For obtaining data from the World Bank API, it is helpful to first obtain a list of country codes and names.
We initialize a folder for the current project that we are working on. And then change to that directory
!mkdir iso2Codes_names
%cd iso2Codes_names
Then we utilize the %%file
command to create the following makefile which will compile our program and create an executable.
%%file makefile
# Set the variable CC to gcc, which is used to build the program
CC=gcc
# Enable debugging information and enable all compiler warnings
CFLAGS=-g -Wall
# Set the bin variable as the name of the binary file we are creating
BIN=iso2Codes
# Create the binary file with the name we put
all: $(BIN)
# Map any file ending in .c to a binary executable.
# "$<" represents the .c file and "$@" represents the target binary executable
%: %.c
# Compile the .c file using the gcc compiler with the CFLAGS and links
# resulting binary with the CURL library
$(CC) $(CFLAGS) $< -o $@ -lcurl
# Clean target which removes specific files
clean:
# Remove the binary file and an ".dSYM" (debug symbols for debugging) directories
# the RM command used -r to remove directories and -f to force delete
$(RM) -rf $(BIN) *.dSYM
The command is used again to create our .c file which contains the code for the program
%%file iso2Codes.c
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* CURL program that retrieves JSON data from the World Bank API */
int main (int argc, char* argv[]) {
// If arguments are invalid then return
if (argc > 1) {
printf("Error. Please try again correctly.\n");
return -1;
}
// Initialize the CURL HTTP connection
CURL *curl = curl_easy_init();
// Bits of the url that are joined together later
char api[] = "https://api.worldbank.org/v2/";
char url[1000];
char label[] = "country/?format=json&per_page=500";
// Check if CURL initialization is a success or not
if (!curl) {
fprintf(stderr, "init failed\n");
return EXIT_FAILURE;
}
// Combine all the bits to produce a functioning url
sprintf(url, "%s%s", api, label);
// Set the url to which the HTTP request will be sent to
// First parameter is for the initialized curl HTTP request, second for the option to be set, and third for the value to be set
curl_easy_setopt(curl, CURLOPT_URL, url);
// If result is not retrieved then output error
CURLcode result = curl_easy_perform(curl);
// If result is not retrieved then output error
if (result != CURLE_OK) {
fprintf(stderr, "download problem: %s\n", curl_easy_strerror(result));
}
// Deallocate memory for the CURL connection
curl_easy_cleanup(curl);
return EXIT_SUCCESS;
}
The folowing program is run, and an executable is created after using the following command:
!make
To output the data from the WOrld Bank API, we enter the following command:
!./iso2Codes | jq '.[1][0]'
{
"id": "ABW",
"iso2Code": "AW",
"name": "Aruba",
"region": {
"id": "LCN",
"iso2code": "ZJ",
"value": "Latin America & Caribbean "
},
"adminregion": {
"id": "",
"iso2code": "",
"value": ""
},
"incomeLevel": {
"id": "HIC",
"iso2code": "XD",
"value": "High income"
},
"lendingType": {
"id": "LNX",
"iso2code": "XX",
"value": "Not classified"
},
"capitalCity": "Oranjestad",
"longitude": "-70.0167",
"latitude": "12.5167"
}
!./iso2Codes | jq '.[1][] | .iso2Code + ": " + .name'
2. Compile a Custom Indicator Dataset#
There are many availabe indicators: https://data.worldbank.org/indicator
We wll select either of the three indicators for this example:
Scientific and Technical Journal Article Data = IP.JRN.ARTC.SC
Patent Applications, residents = IP.PAT.RESD
GDP per capita (current US$) Code = NY.GDP.PCAP.CD
Note that these three selected indictaors have a CC-BY 4.0 license We will compile this indicator data for the United States (US) and United Kingdom (GB)
We change the directory of the World_Bank folder to create a new one for our project
%cd ..
We set a directory where we want the WorldBank directory for the custom indicator project
!mkdir Custom_indicator
Then we change the directory to the folder we created
%cd Custom_indicator
Then we utilize the %%file
command to create the following makefile which will compile our program and create an executable.
%%file makefile
# Set the variable CC to gcc, which is used to build the program
CC=gcc
# Enable debugging information and enable all compiler warnings
CFLAGS=-g -Wall
# Set the bin variable as the name of the binary file we are creating
BIN=custom_indicator
# Create the binary file with the name we put
all: $(BIN)
# Map any file ending in .c to a binary executable.
# "$<" represents the .c file and "$@" represents the target binary executable
%: %.c
# Compile the .c file using the gcc compiler with the CFLAGS and links
# resulting binary with the CURL library
$(CC) $(CFLAGS) $< -o $@ -lcurl
# Clean target which removes specific files
clean:
# Removes the binary file and an ".dSYM" (debug symbols for debugging) directories
# the RM command used -r to remove directories and -f to force delete
$(RM) -rf $(BIN) *.dSYM
The command is used again to create our .c file which contains the code for the program
%%file custom_indicator.c
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*CURL program that retrieves JSON data from the World Bank API
This program allows custom indicator data set to be used along with the country specified*/
/* We are going to be inputting the custom indicator and country like this: ./custom_indicator -c "UK" -i "IP.JRN.ARTC.SC"
If the arguments are missing then we use the default: "US" "IP.JRN.ARTC.SC" */
int main (int argc, char* argv[]) {
// If arguments are invalid then return
if (argc > 5) {
printf("Error. Please try again correctly.\n");
return -1;
}
// Default country and indicator codes
char country[10] = {};
char indicator[100] = {};
// If there is ./custom_indiactor -c/-i
if ((argc == 1) || ((argc == 2) && ((strcmp(argv[1], "-c")==0) || (strcmp(argv[1], "-i")==0)))) {
//these arguments run the default parameters and keeps the codes as they are
strcat(country,"US");
strcat(indicator, "IP.JRN.ARTC.SC");
}
// If there is ./custom indicator -c "UK"
else if ((argc == 3) && (strcmp(argv[1], "-c")==0)) {
// Only the country code is changed
strcat(country,argv[2]);
strcat(indicator, "IP.JRN.ARTC.SC");
}
// If there is ./custom indicator -c "UK" -i
else if ((argc == 4) && (strcmp(argv[1], "-c")==0) && (strcmp(argv[3], "-i")==0)) {
// Only the country code is changed
strcat(country,argv[2]);
strcat(indicator, "IP.JRN.ARTC.SC");
}
// If there is ./custom indicator -c "UK" -i "IP.JRN.ARTC.SC"
else if ((argc == 5) && (strcmp(argv[1], "-c")==0) && (strcmp(argv[3], "-i")==0)) {
// Both the country and indicator codes are changed
strcat(country,argv[2]);
strcat(indicator, argv[4]);
}
// If there is ./custom indicator -i "IP.JRN.ARTC.SC"
else if ((argc == 3) && (strcmp(argv[1], "-i")==0)) {
// Only the indicator code is changed
strcat(country,"US");
strcat(indicator, argv[2]);
}
// If there is ./custom indicator -i "IP.JRN.ARTC.SC" -c
else if ((argc == 4) && (strcmp(argv[1], "-i")==0) && (strcmp(argv[3], "-c")==0)) {
// Only the indicator code is changed
strcat(country,"US");
strcat(indicator, argv[2]);
}
// If there is ./custom indicator -i "IP.JRN.ARTC.SC" -c "UK"
else if ((argc == 5) && (strcmp(argv[1], "-i")==0) && (strcmp(argv[3], "-c")==0)) {
// Both the indicator and country codes are changed
strcat(country,argv[4]);
strcat(indicator, argv[2]);
}
else{
printf("usage: ./custom_indicator [-i] indicator [-c] country\n\n");
printf("the custom_indicator program is used to retrieve json data from the World Bank API\n\n");
printf("optional arguments\n");
printf("\t -i indicator optional custom indicator code; default is 'IP.JRN.ARTC.SC', see: https://data.worldbank.org/indicator\n");
printf("\t -c country optional custom country code; default is 'US'\n");
return -1;
}
// Initialize the CURL HTTP connection
CURL *curl = curl_easy_init();
// Bits of the url that are joined together later
char api[] = "https://api.worldbank.org/v2/";
char type1[] = "country/";
char type2[] = "/indicator/";
char url[1000];
char label[] = "/?format=json&per_page=500";
// Check if CURL initialization is a success or not
if (!curl) {
fprintf(stderr, "init failed\n");
return EXIT_FAILURE;
}
// Combine all the bits to produce a functioning url
sprintf(url, "%s%s%s%s%s%s", api, type1 , country, type2, indicator, label);
// Set the url to which the HTTP request will be sent to
// First parameter is for the initialized curl HTTP request, second for the option to be set, and third for the value to be set
curl_easy_setopt(curl, CURLOPT_URL, url);
// If result is not retrieved then output error
CURLcode result = curl_easy_perform(curl);
// If result is not retrieved then output error
if (result != CURLE_OK) {
fprintf(stderr, "download problem: %s\n", curl_easy_strerror(result));
}
// Deallocate memory for the CURL connection
curl_easy_cleanup(curl);
return EXIT_SUCCESS;
}
!make
To output the data from the World Bank API with the default indicator and country (IP.JRN.ARTC.SC, US), we enter the following command:
!./custom_indicator | jq '.[1][] | "\(.date)':' \(.value)"' | head -n 10
"2022: null"
"2021: null"
"2020: 455855.57"
"2019: 438020.45"
"2018: 435033.88"
"2017: 430198.17"
"2016: 428476.45"
"2015: 428203.78"
"2014: 428140.59"
"2013: 426596.66"
To output the data from the World Bank API with the custom indicator and country, we enter the following command:
!./custom_indicator -i 'NY.GDP.PCAP.CD' -c 'GB' | jq '.[1][] | "\(.date)':' \(.value)"' | head -n 10
"2022: 45850.4261222629"
"2021: 46585.8975644567"
"2020: 40318.4169225055"
"2019: 42747.080460496"
"2018: 43306.3083049317"
"2017: 40622.6893883232"
"2016: 41146.0773555246"
"2015: 45071.0743234873"
"2014: 47447.5889322667"
"2013: 43449.0917173139"
To compile a custom indicator dataset we need to have parse the data into a single .txt file
We enter the following command, to output first indicator data to the .txt file:
!./custom_indicator -i 'NY.GDP.PCAP.CD' -c 'US' | jq '.[1][] | "\(.date)':' \(.value)"' > output1.txt
We do the same for the 2nd and the 3rd indicator data:
!./custom_indicator -i 'IP.JRN.ARTC.SC' -c 'US' | jq '.[1][] | "\(.date)':' \(.value)"' > output2.txt
!./custom_indicator -i 'IP.PAT.RESD' -c 'US' | jq '.[1][] | "\(.date)':' \(.value)"' > output3.txt
We then join the data together in different columns and output it to the specified .txt file:
!join output1.txt output2.txt > output12.txt
The same is done to create the final combined data set:
!join output12.txt output3.txt > output_combined.txt
We then remove the "
and :
to create the custom data set
!cat output_combined.txt | tr -d '",:' | head -5
2022 76398.5917422054 null null
2021 70219.472454115 null null
2020 63528.6343027508 455855.57 269586
2019 65120.3946628653 438020.45 285113
2018 62823.309438197 435033.88 285095