How to Map Nested JSON Fields to Table Columns in TableCrafter

REST APIs rarely return flat key-value objects. Most return nested structures, objects inside objects, arrays of objects, mixed types, and knowing how to map those structures to table columns is one of the most practical skills for building API-powered tables in TableCrafter. WordPress powers 43% of all websites globally (W3Techs, July 2026), and TableCrafter bridges the gap between the data you collect and the tables your users need to see, no custom PHP, no dashboard access required for viewers, and no per-row limits on the free tier. The free version on WordPress.org supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV/PDF, role-based column visibility, and auto-refresh. Every table embeds on any page with a [tablecrafter] shortcode or the native Gutenberg block. Airtable views can filter up to 100,000 records with sub-second response times on Pro plans (Airtable documentation, 2025).
Why Nested JSON?
A typical API response might look like this user record from JSONPlaceholder:
{
"id": 1,
"name": "Leanne Graham",
"address": {
"street": "Kulas Light",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net"
},
"tags": ["admin", "user", "beta"]
}
If you try to map the field address as a column, TableCrafter will render the entire object as a JSON string, not useful. You need to reference individual leaf values.
Real-world REST APIs almost universally nest their data because the structure reflects natural hierarchies: a user has an address, an address has a city, an order has line items. Flattening all of this into a single-depth object would require verbose combined key names and make the payload harder to read as the data model evolves. Working with nested data in TableCrafter therefore requires mapping individual leaf paths rather than top-level keys.
TableCrafter handles common envelope patterns automatically. When the HTTP response is a top-level JSON array, each element becomes one table row. When the response is a JSON object containing a single key whose value is an array, the plugin walks into that array directly, so a response shaped as {"data": [...]} produces rows without manual path configuration. More complex envelopes with multiple top-level keys require you to specify a dot-path in the data source settings to identify which key holds the row array.
Dot Notation for Nested Objects?
TableCrafter uses dot-notation paths to reference nested fields. In the column builder, set the Field Path to the dot-separated path from the root of each object to the value you want.
For the example above:
address.city→ Gwenboroughaddress.zipcode→ 92998-3874address.geo.lat→ -37.3159 (three levels deep)company.name→ Romaguera-Cronacompany.catchPhrase→ Multi-layered client-server neural-net
The path is case-sensitive and must match the exact key names in the JSON response. There is no depth limit, paths like a.b.c.d.e are valid.
This configuration interacts with any caching or CDN layer active on your WordPress installation. If you use WP Rocket, LiteSpeed Cache, or a CDN such as Cloudflare, flush the page cache after making this change to ensure the updated configuration is reflected in the cached HTML served to visitors. TableCrafter's server-side output is regenerated on the next uncached request.
How Does Auto-Detection of Nested Fields Work?
When you connect a REST API data source and open the column builder, TableCrafter fetches the first object from the response and recursively enumerates all leaf paths. The field selector dropdown will list address.city, address.geo.lat, and so on automatically, you do not need to type paths manually unless the field is conditional (only present in some records).
After completing this step, verify the result by viewing the page as a logged-out visitor in an incognito window. This confirms the table behaves correctly for public visitors rather than reflecting admin-level permissions that may hide configuration issues during initial setup. Check both the rendered output and the browser console for any JavaScript errors.
How Does Arrays of Primitive Values Work?
The tags field in the example is an array of strings: ["admin", "user", "beta"]. Mapping the field tags directly will render the values joined as a comma-separated string in the table cell:
admin, user, beta
This is TableCrafter's default behavior for primitive arrays. It is suitable for tags, categories, and similar multi-value fields where a compact representation is appropriate. You cannot filter on individual array elements using this mapping; the filter will match against the full joined representation.
Arrays of numbers behave the same way: a field returning multiple product IDs or category codes displays all values together in one cell. Sorting on an array field uses the full string representation rather than individual element values, so numeric sorting will not produce expected results on fields that contain arrays of integers. If your use case requires sortable or filterable individual values, use indexed dot notation such as tags.0 to access only the first element as a dedicated column.
When a primitive array is empty, the cell renders blank, visually indistinguishable from a row where the field was never set. If you need a placeholder for empty array cells, configure a column-level default value in the Display settings to show a fallback string such as "None" when the field returns an empty result. For display-only scenarios where filtering on individual array elements is not required, the default joined representation is sufficient without any additional configuration.
How Does Arrays of Objects Work?
Some APIs return arrays of nested objects. A common example is an order with line items:
{
"order_id": 1001,
"customer": "Jane Smith",
"items": [
{"product": "Widget A", "qty": 2, "price": 9.99},
{"product": "Widget B", "qty": 1, "price": 14.99}
]
}
If you map items, the cell will contain a JSON array string, not readable. Instead, use indexed dot notation to reference specific elements or specific fields within elements:
items.0.product→ Widget A (first item's product name)items.0.price→ 9.99
This approach works well when there is always a primary item. For scenarios where you need to display all items in a single cell, map the parent field (items) and TableCrafter will render a compact JSON representation. For a cleaner display, use a custom column template (see below).
The column mapping you define here is stored as a JSON configuration in the WordPress database. You can export this configuration using the TableCrafter export tool and import it to another table or another site. This is useful when replicating a table layout across multiple pages or when migrating a table to a staging environment for testing before going live.
What Is Flattening Arrays of Objects: The Extract Pattern?
When an API returns one parent record per item in a nested array, and you want one table row per nested item rather than one row per parent, use the Array Root setting on the data source configuration screen.
For example, if the API returns:
{
"team": "Engineering",
"members": [
{"name": "Alice", "role": "Lead"},
{"name": "Bob", "role": "Developer"}
]
}
And you want one row per member, set the Root Path to members and map name and role as columns. This yields two rows instead of one.
If the response is an array of parent objects each with a nested array, this flattening is not currently supported natively, each parent object becomes one row, and nested arrays within it render as joined strings or JSON.
TableCrafter re-fetches this data on each page load by default. If your data source updates infrequently and your site has significant traffic, enable the built-in caching option in the table's Performance tab. This stores the fetched data for a configurable number of minutes and serves it from WordPress transients, reducing API calls to the source and improving page load time for visitors.
How Does Column Templates for Custom Rendering Work?
For complex nested data that does not fit cleanly into a single field path, TableCrafter column templates let you compose multiple fields into one cell using a simple placeholder syntax:
{{address.street}}, {{address.city}} {{address.zipcode}}
This renders as Kulas Light, Gwenborough 92998-3874 in a single column. Templates support any field path that dot-notation can address, including nested values.
Templates are especially useful for presenting address components, building full names from first and last name fields at different nesting levels, or composing identifiers that span multiple fields in the same record. Each placeholder resolves independently per row, so a template with three placeholders performs three path lookups for every cell it renders.
If a placeholder references a path that does not exist in a particular row, it resolves to an empty string and the surrounding literal text in the template still appears. A template like {{address.street}}, {{address.city}} renders as , Gwenborough for a record where address.street is absent, which may not be desirable for nullable fields. For fields that can be missing in some records, consider handling the null case at the data source level, or use a single-field column alongside a template column to avoid partially blank composite output.
How Does Common Edge Cases Work?
Field names containing dots
If your API returns a key that literally contains a dot, for example {"user.name": "Alice"}, this creates an ambiguity in dot-notation path syntax. TableCrafter's path resolver splits the field path string on every . character, so a key named user.name cannot be addressed by a simple dot path: the parser treats it as navigation through a user object to a nested name key, not as access to a top-level key whose name contains a period.
Most well-designed REST APIs do not use periods in key names because the character has reserved meaning in many query and template languages. If you are consuming a fixed third-party API that uses dots in its keys and you cannot modify the source, a practical workaround is to add a proxy endpoint to your WordPress site that fetches the external data and returns a copy with sanitized key names, using underscores or camelCase in place of dots. TableCrafter can then point to the local proxy URL instead of the external API directly.
If only a small number of dot-key fields are affected and those fields are non-critical for your table, the simplest option is to exclude them from the column mapping entirely and focus on the cleanly named fields the API provides.
Null values in nested paths
If an intermediate key is null, for example address is null rather than an object, resolving address.city would normally throw an error. TableCrafter handles this gracefully by returning an empty string rather than crashing. Rows with null intermediate values render blank cells in the affected columns.
This null-safety extends to any depth in the path. A three-level path such as company.address.city returns an empty string if company is null, if address is null, or if city itself is null or simply not present in the object. The resolver checks each segment before descending further, so a missing key at any level produces the same empty-string result as a null value at that level.
Empty strings and null values both render as blank cells with no visual distinction between them. If your use case requires distinguishing between an explicitly null field and an empty string, pre-process the data at the API level to substitute a placeholder such as "N/A" for null values before the response reaches TableCrafter. Filters applied to nullable columns match against the empty string representation, so filtering for blank cells captures both nulls and genuinely empty strings in the same result set.
Mixed types
Some APIs return a field as a string in some records and an integer in others. TableCrafter coerces values to strings for display. If you configure a column with type Number for sorting purposes and the field occasionally returns a string, sorting will fall back to lexicographic order for records where the value cannot be parsed as a number.
Column type inference runs on a sample of the first rows fetched from the data source. If the sampled rows all carry numeric values for a field, the column is typed as Number. If a later row delivers a string value for the same field, that row sorts using string comparison rather than numeric comparison, so "10" sorts between "1" and "2" instead of after "9". Ensuring the API returns consistent types across all records avoids this inconsistency.
For fields that store identifiers formatted as strings of digits, such as order numbers or product codes, set the column type explicitly to Text. Text columns sort alphabetically, which is predictable and consistent even when some values contain non-numeric characters. Configure the explicit type in the column settings Display tab after the column is added, rather than relying on auto-inference from the initial sample batch.
Boolean values
JSON booleans (true / false) are decoded as PHP boolean values when the response is parsed. In many cases, true renders as the digit 1 and false renders as an empty cell due to PHP's standard boolean-to-string coercion. Verifying the actual output in a live table before publishing is advisable, since the display may depend on how the column type handles the value.
For a consistent, readable representation, set the column's cell renderer to Badge and define two mapping entries keyed to whatever string the column actually displays for each boolean state. If true appears as "1", map "1" to a green badge and add a corresponding entry for the false representation. This approach is reliable regardless of the underlying type coercion because you base the badge keys on the observed cell output rather than on assumptions about the boolean rendering.
Boolean fields used as active/inactive or enabled/disabled flags are common candidates for badge rendering. A table showing API configuration records or feature flag states benefits from a green badge for the active state and a muted gray for the inactive state rather than displaying raw boolean output.
What Is Practical Example: GitHub Repository List?
The GitHub public API returns a complex nested structure. Here are the field paths to extract common values from https://api.github.com/users/octocat/repos:
name→ Repository namedescription→ Repo descriptionstargazers_count→ Star countlanguage→ Primary languageowner.login→ Owner usernamelicense.name→ License (will be blank for repos with no license set)topics→ Joined array of topic strings
The shortcode to render this as a searchable table:
[tablecrafter id="3" search="true" filter="true"]
Configure this as a JSON data source in TableCrafter by entering the API URL in the data source settings. The response is a top-level JSON array where each element is a repository object, so TableCrafter auto-detects the row array without requiring a manual dot-path setting. The GitHub REST API paginates results using an RFC 5988 Link response header with a rel="next" URL; enable the paginated fetch option in the data source settings to follow this header automatically and collect repositories across multiple pages in a single table.
GitHub's unauthenticated API allows 60 requests per hour per IP address. Enable the table's caching option in the Performance settings to store the fetched rows in WordPress transients, so the data is re-fetched only at the configured interval rather than on every page load. A cache duration of 10 to 30 minutes keeps the repository list reasonably current while staying well within the hourly rate limit. For authenticated requests to private repositories or to raise the rate limit, add a personal access token as an Authorization header in the data source settings.
Frequently Asked Questions
Why Nested JSON?
Nested JSON is the standard output format for most REST APIs because it models hierarchical real-world data accurately. A user has an address; an address has a city; an order has line items, each with its own product details. Structuring all of this as a flat key-value object would require verbose combined key names and make the payload harder to read as the data model evolves. Nesting is therefore the norm, not the exception, for any API that returns records with more than a handful of fields.
When you connect a JSON or REST API source to TableCrafter, you need to pull values from specific levels of this hierarchy rather than displaying whole sub-objects as JSON strings. Dot-notation path resolution lets you write address.city to extract the city string from inside the address object, or items.0.product to get the first line item's product name from inside an orders array. TableCrafter also auto-detects common envelope patterns where the row array is wrapped inside a named key, reducing manual path configuration for typical API responses.
What Is TableCrafter?
TableCrafter is a WordPress plugin that turns data from Gravity Forms, Google Sheets, Airtable, Notion, REST APIs, CSV files, and WooCommerce into interactive, sortable, filterable frontend tables. Embed any table on any WordPress page with the [tablecrafter] shortcode or the native Gutenberg block. No PHP or custom development required. The free version supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV and PDF, role-based column visibility, and auto-refresh.
Does this require PHP or developer skills?
No. TableCrafter is configured entirely through the WordPress admin interface. You choose your data source, map fields to columns, and set display preferences using point-and-click controls. Embedding uses the [tablecrafter] shortcode or the native Gutenberg block.
Is the free version sufficient or do I need Pro?
The free plugin on WordPress.org supports CSV, JSON, Google Sheets, and Excel sources with unlimited tables, rows, and columns. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST API sources, inline cell editing, bulk row actions, export to CSV and PDF, role-based column visibility, and auto-refresh every N seconds.
Ready to try it?
TableCrafter is free on WordPress.org. Pro unlocks inline editing, role-based permissions, and advanced data sources.