Transform REST API Responses into Readable ASCII Tables with CLI Tools

Introduction

Ever fetched data from a REST API only to get buried in nested JSON that's hard to scan quickly in the terminal? Whether you're debugging an endpoint, building a script, or just exploring data, you need a way to simplify and visualize it without firing up a full IDE or scripting language.

In this post, we'll pull country details from the REST Countries API, strip it down to essentials like flags, names, and populations, and pipe it straight into a clean ASCII table — all from the command line.

You'll end up with a pipeline that's fast, repeatable, and perfect for one-off queries or automation.

Install the packages

aux4 aux4 pkger install aux4/adapter aux4/2table

Fetching Country Data from the API

Start with the basics: grabbing the raw data. The REST Countries API gives you a massive JSON array with details on every country. We'll focus on key fields like codes, names, flags, capitals, languages, populations, timezones, and continents.

Run this to see the structure:

curl 'https://restcountries.com/v3.1/all?fields=cca3,name,flag,capital,languages,population,timezones,continents' \
  --silent | head -c 1000

The output looks something like this:

[{"name":{"common":"Lithuania","official":"Republic of Lithuania","nativeName":{"lit":{"official":"Lietuvos Respublikos","common":"Lietuva"}}},"cca3":"LTU","capital":["Vilnius"],"languages":{"lit":"Lithuanian"},"flag":"🇱🇹","population":2794700,"timezones":["UTC+02:00"],"continents":["Europe"]}]

It's a lot — over 250 countries with nested objects everywhere. Languages are key-value pairs (e.g., {"lit": "Lithuanian"}), capitals and continents are arrays, and you just want the essentials.

Simplifying the JSON Response

Now, transform that raw mess into something usable. Create a countries.yaml config file to define exactly what to extract:

config:
  countries:
    format: json
    mapping:
      flag: $.flag
      cca3: $.cca3
      name: $.name.common
      capital: $.capital[0]
      continent: $.continents[0]
      languages: $.languages
      timezones: $.timezones
      population: $.population

This grabs the flag emoji, country code, common name, first capital (handling multiples like South Africa's), first continent, the full languages object, timezones array, and population.

Pipe the API response through it:

curl 'https://restcountries.com/v3.1/all?fields=cca3,name,flag,capital,languages,population,timezones,continents' \
  --silent \
  | aux4 adapter map --configFile countries.yaml --config countries \
  | head -c 2000

Here's a snippet of the cleaned-up JSON:

[
  {
    "flag": "🇱🇹",
    "cca3": "LTU",
    "name": "Lithuania",
    "capital": "Vilnius",
    "continent": "Europe",
    "languages": {
      "lit": "Lithuanian"
    },
    "timezones": "UTC+02:00",
    "population": 2794700
  },
  {
    "flag": "🇨🇱",
    "cca3": "CHL",
    "name": "Chile",
    "capital": "Santiago",
    "continent": "South America",
    "languages": {
      "spa": "Spanish"
    },
    "timezones": "UTC-06:00, UTC-04:00",
    "population": 19116209
  }
]

Notice how capitals and continents take the first item, timezones join into a string, and languages stay as an object for now (we'll handle display next).

For multi-language countries like Bolivia:

{
  "cca3": "BOL",
  "name": "Bolivia",
  "capital": "Sucre",
  "continent": "South America",
  "languages": {
    "aym": "Aymara",
    "grn": "Guaraní",
    "que": "Quechua",
    "spa": "Spanish"
  },
  "timezones": "UTC-04:00"
}

And for multi-capital countries like South Africa, $.capital[0] picks the first one:

{
  "cca3": "ZAF",
  "name": "South Africa",
  "capital": "Pretoria",
  "continent": "Africa"
}

This keeps things simple — no more deep nesting, just the fields you need.

Rendering Data as an ASCII Table

With the JSON streamlined, pipe it to aux4 2table. Specify columns and let it handle alignment, even for objects and arrays:

curl 'https://restcountries.com/v3.1/all?fields=cca3,name,flag,capital,languages,population,timezones,continents' \
  --silent \
  | aux4 adapter map --configFile countries.yaml --config countries \
  | aux4 2table flag,cca3,name,capital,continent,languages,timezones,population

The result is a neat ASCII table:

 flag  cca3  name        capital     continent      languages         timezones             population
 🇱🇹   LTU   Lithuania   Vilnius     Europe         lit: Lithuanian   UTC+02:00             2794700
 🇨🇱   CHL   Chile       Santiago    South America  spa: Spanish      UTC-06:00, UTC-04:00  19116209
 🇧🇯   BEN   Benin       Porto-Novo  Africa         fra: French       UTC+01:00             12123198
 🇫🇰   FLK   Falkland    Stanley     South America  eng: English      UTC-04:00             2563
 🇬🇪   GEO   Georgia     Tbilisi     Asia           kat: Georgian     UTC+04:00             3714000
 ...

Languages show as lit: Lithuanian (key-value pairs flattened), timezones as comma-separated, and populations right-aligned.

For better labels, rename columns using the field:"Label" syntax:

curl 'https://restcountries.com/v3.1/all?fields=cca3,name,flag,capital,languages,population,timezones,continents' \
  --silent \
  | aux4 adapter map --configFile countries.yaml --config countries \
  | aux4 2table flag,cca3:"Code",name:"Country",capital:"Capital",continent:"Region",languages:"Languages",timezones:"Time Zones",population:"Pop."

Output:

 flag  Code  Country     Capital     Region         Languages         Time Zones            Pop.
 🇱🇹   LTU   Lithuania   Vilnius     Europe         lit: Lithuanian   UTC+02:00             2794700
 🇨🇱   CHL   Chile       Santiago    South America  spa: Spanish      UTC-06:00, UTC-04:00  19116209
 🇧🇯   BEN   Benin       Porto-Novo  Africa         fra: French       UTC+01:00             12123198
 ...

Want Markdown output instead? Swap the format:

curl 'https://restcountries.com/v3.1/all?fields=cca3,name,flag,capital,languages,population,timezones,continents' \
  --silent \
  | aux4 adapter map --configFile countries.yaml --config countries \
  | aux4 2table --format md flag,cca3,name,capital,continent,languages,timezones,population
flagcca3namecapitalcontinentlanguagestimezonespopulation
🇱🇹LTULithuaniaVilniusEuropelit: LithuanianUTC+02:002794700
🇨🇱CHLChileSantiagoSouth Americaspa: SpanishUTC-06:00, UTC-04:0019116209
🇧🇯BENBeninPorto-NovoAfricafra: FrenchUTC+01:0012123198

Perfect for pasting into READMEs or pull request descriptions.

Conclusion

With two aux4 packages and a YAML config, you get a dead-simple CLI pipeline to fetch API data, transform it with precise mappings, and view it as a table — all without leaving your terminal.

The key idea: aux4/adapter handles the data shaping (flattening nested JSON, picking array elements, joining values), and aux4/2table handles the presentation. You can swap the API, change the mapping, or pipe the output into other tools.

See Also