API and JSON Exploration
VisiData can consume JSON from any source — local files, piped curl output, or JSONL streams. Nested fields expand interactively with (. This makes VisiData a fast, zero-code alternative to jq for exploratory API work.
Learning Focus
The core pattern: curl -s URL | vd -f json → expand nested ( → filter | → export Ctrl+S. Once you know this loop, any API response becomes an interactive sheet.
Sample API-Style JSON
mkdir -p ~/github/practice-folder/visidata/07-api
cat > ~/github/practice-folder/visidata/07-api/01-github-repos.json << 'EOF'
[
{"id": 1, "name": "visidata", "owner": {"login": "saulpw"}, "stargazers_count": 7200, "language": "Python", "archived": false},
{"id": 2, "name": "datasette", "owner": {"login": "simonw"}, "stargazers_count": 9100, "language": "Python", "archived": false},
{"id": 3, "name": "csvkit", "owner": {"login": "wireservice"}, "stargazers_count": 5800, "language": "Python", "archived": false},
{"id": 4, "name": "old-tool", "owner": {"login": "user99"}, "stargazers_count": 120, "language": "Shell", "archived": true}
]
EOF
Open JSON from a Local File
vd ~/github/practice-folder/visidata/07-api/01-github-repos.json
Initial view — nested columns appear as {...}:
id name owner stargazers_count language archived
1 visidata {...} 7200 Python False
2 datasette {...} 9100 Python False
3 csvkit {...} 5800 Python False
4 old-tool {...} 120 Shell True
Pipe Live from an API
curl -s https://api.github.com/repos/saulpw/visidata | vd -f json
Or for a list endpoint:
curl -s "https://api.github.com/search/repositories?q=visidata&per_page=10" | vd -f json
note
GitHub API returns a JSON object with a items key containing the list. Navigate with Enter on the items column to open the list as a new sheet.
Expand Nested Columns
The owner column shows {...} — expand it:
# Move cursor to 'owner' column
(
# Expands one level: owner.login, owner.id, etc. appear as new columns
After expanding:
id name owner.login stargazers_count language archived
1 visidata saulpw 7200 Python False
2 datasette simonw 9100 Python False
For deeply nested JSON:
# Expand all nested columns one level deep
g(
# Expand to depth 2
z( 2
Collapse expanded columns:
) # collapse current expanded column
g) # collapse all
Cast and Analyze
# Cast stargazers_count to int
# Move to 'stargazers_count' column → press #
# Sort by stars descending
]
Result — most-starred repos first:
name owner.login stargazers_count language
datasette simonw 9100
visidata saulpw 7200
csvkit wireservice 5800
old-tool user99 120
Filter Results
# Filter out archived repos
z|
# Enter: archived == False
# Open filtered sheet
"
Frequency Table on Language
# From filtered sheet, move to 'language' column
Shift+F
Result:
language count percent
Python 3 100%
Export Results
# Export the filtered, expanded sheet
Ctrl+S
# Enter: ~/github/practice-folder/visidata/07-api/active-repos.csv
Complete API Workflow
curl -s <API_URL> | vd -f json
1. ( on nested column → expand owner.login
2. # on numeric column → cast to int (stargazers_count)
3. ] → sort by stars descending
4. z| archived == False → " → filter to active repos
5. Shift+F on language → language distribution
6. Ctrl+S → export as CSV
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| JSON opens as single text column | Not valid JSON | Validate with echo "$json" | python3 -m json.tool |
| Nested columns don't expand | Column type is string, not dict | Ensure response is parsed as JSON (-f json) |
| API returns paginated data | Single page only | Loop curl and concat with jq -s '.[0] + .[1]' |
| Rate limit error from API | Too many requests | Use --max-rows to sample; add auth header with -H |
Hands-On Practice
vd ~/github/practice-folder/visidata/07-api/01-github-repos.json
# 1. View the sheet — notice owner column shows {...}
# 2. Move to 'owner' column → press ( → owner.login appears
# 3. Move to 'stargazers_count' → press # → cast to int
# 4. Press ] → sort by stars descending
# 5. Press z| → Enter: archived == False → select active repos
# 6. Press " → open filtered sheet
# 7. Move to 'language' → Shift+F → see language breakdown
# 8. Press q → back to filtered sheet
# 9. Press Ctrl+S → save as /tmp/active-repos.csv