Worked examples: Extract Values with the keys Syntax.
The syntax is implemented by HuxxConnectCoreArrayKeyExtractor (src/Core/ArrayKeyExtractor.php): parse() turns a keys string into path(s), extract() resolves path(s) against the decoded response array. The shortcode keys attribute and the template functions’ keys argument (string form) both go through parse(); an array passed to the keys argument goes straight to extract().
Grammar
keys = brace-list | bare-list | bare-path
brace-list = "{" path "}" *( "," "{" path "}" )
bare-list = path 1*( "," path )
bare-path = path
path = segment *( "." segment )
segment = key | index | "[]"
key = string array key ; any characters except "." (and "}" inside braces, "," in bare lists)
index = numeric list position, zero-based
"[]" = wildcard: fan out across every item of a sequential list
There is no escaping mechanism: a response key that itself contains ., ,, {, or } cannot be addressed.
Parsing rules (parse())
Applied to the raw string in order:
- Leading/trailing whitespace is trimmed; an empty string parses to
""(extraction is skipped by the shortcode;extract()returnsnullfor it). - Brace notation — if the string contains
{, all{…}groups are captured (/{([^}]+)}/), each trimmed. One group → single path (string). Multiple groups → list of paths. Text outside braces is ignored. Empty braces{}or a{with no well-formed group fall through to bare handling. - Bare notation with commas — the string splits on
,; each piece is trimmed and becomes a path. - Bare single path — anything else is one path.
| Input | Parses to |
|---|---|
products.0.title | "products.0.title" |
{products.0.title} | "products.0.title" |
{title},{price} | ["title", "price"] |
title, price | ["title", "price"] |
{a.b}, ignored, {c} | ["a.b", "c"] — non-brace text ignored once braces are present |
{} | falls through to bare: "{}" (resolves to null) |
"" | "" |
Resolution rules (extract())
Input forms:
$keys form | Result |
|---|---|
| string path | The value at that path, or null if not found. |
| array, 1 entry | Same as a string path — unwrapped raw value. |
| array, 2+ entries | Associative array keyed by each full dot path; paths resolving to null are omitted. |
| empty array (or non-array, non-string) | The source data, unchanged. |
Traversal (paths without []):
- Each segment indexes into the current array with
isset(). A missing key returnsnullfor the whole path. - Because
isset()is used, a key whose value is literallynullis indistinguishable from a missing key — the path resolves tonulleither way, and is omitted from multi-key results. - Numeric segments address list positions (
products.0= first item). No negative indexes, no ranges. - Traversal stops with
nullif an intermediate value is a scalar (you cannot descend into a string or number).
Wildcard ([]) resolution:
- A
[]segment fans out across every element of the current context. Each context must be a sequential list (keys0..n-1; the empty array counts as sequential) — non-list contexts are skipped. - Remaining segments resolve against every fanned-out element; elements missing the segment are dropped.
- If any step leaves zero surviving contexts, the whole path resolves to
null. - Multiple wildcards nest:
products.[].reviews.[].ratingcollects every rating of every product. - Final results are flattened one level: surviving values that are themselves sequential lists are merged item-by-item into the single result list; other values are appended as-is.
Examples
Against the DummyJSON demo response (GET https://dummyjson.com/products, wrapped list root products):
| keys | Result |
|---|---|
total | 194 |
products.0.title | "Essence Mascara Lash Princess" |
{products.0.title},{products.0.price} | {"products.0.title": "Essence Mascara Lash Princess", "products.0.price": 9.99} |
products.[].title | ["Essence Mascara Lash Princess", "Eyeshadow Palette with Mirror", …] |
products.[].reviews.[].rating | [3, 4, 5, …] — flattened across all products |
products.99999.title | null |
[].title | null — the response root is keyed, not a list |
Runnable example:
<?php
$titles = huxx_api( 'demo_api', 'get_products', array( 'keys' => 'products.[].title' ) );
Output (truncated):
["Essence Mascara Lash Princess", "Eyeshadow Palette with Mirror"]
Warning: the
[]wildcard cannot be used inside a shortcode attribute. WordPress terminates a shortcode at the first]it finds, sokeys="products.[].title"cuts the tag off mid-attribute and the keys path is never applied. Wildcard paths work only through the PHPhuxx_api()function; all other keys forms work in both the shortcode and PHP.
Edge cases
| Case | Behavior |
|---|---|
| Path not found | null (single path); omitted (multi-key). |
Value is literally null | Treated as not found. |
Non-array response (JSON String / Raw results, or after a scalar extraction) | Extraction is skipped by both the shortcode and template functions — keys only applies to arrays. |
[] on an associative array | That context is skipped; if no list contexts remain, the path is null. |
[] on an empty list | No surviving contexts → null. |
| Whitespace around paths or inside braces | Trimmed. |
| Duplicate paths in a multi-key list | Collapse to one entry (results are keyed by path). |
Key containing . in the response | Not addressable — the dot always splits segments. |