jsontree — u_pbt_jsontree #
← Component reference · Guide contents
jsontree shows a JSON value as a collapsible tree, coloured by type: a config screen, an API response, an integration debug. You set the JSON text in
is_json, the component shows it; a click on a node reports its path (ue_node_clicked), invalid JSON raisesue_error. It changes nothing: it is a VIEWER.
▶ See it live — Demo application, JSON tree tile, with the code and this page side by side.
At a glance #
| Userobject | u_pbt_jsontree |
| Input | The JSON text, in is_json (a string) |
| Fold / unfold | Each container by its + / − marker in the line-number margin, by its path (of_expand_path, of_collapse_path), or all at once (of_expand_all, of_collapse_all) |
| Feedback | A click on a node gives its path (ue_node_clicked), the path of n_pbt_json: lines/1/sku; invalid JSON raises ue_error |
| Faithful | Every number and every key is shown as received: a 64-bit id stays exact, 1.10 stays 1.10, a duplicate key keeps both members |
Quick start #
// Show an API response as a tree
uo_json.is_json = inv_rest.of_response_text()
// Fold everything, then let the user open what interests them
uo_json.of_collapse_all()
// ue_node_clicked : the path of the node clicked ("lines/1/sku"), the path of
// n_pbt_json -> of_get_string(as_path) on the same text reads its value
Properties #
| Property | Type | Default | Description |
|---|---|---|---|
is_json | string | "" | The JSON text to show. An object, an array, a value; read and shown as a tree, every number and every key as received. Empty clears the tree, without an error; invalid JSON raises ue_error and shows nothing. Reads back exactly as it was set |
ib_wrap | boolean | true | Long lines wrap (true, the default) or stay on one line with a horizontal scrollbar (false) — a code-editor feel |
ib_search_enabled | boolean | true | Ctrl+F in the tree opens a search box — the same search as of_search: type to highlight, Enter or F3 next, Shift+Enter or Shift+F3 previous, Escape closes. false leaves the shortcut to an application that searches from its own box. The box carries two toggles before the counter, Aa (ib_find_match_case) and ab (ib_find_whole_word); changing an option restarts the current search from its first occurrence |
ib_find_match_case | boolean | false | Search option: finds only the text with the same case. The Aa toggle of the search box (Ctrl+F) is the same switch; applies to of_search and to what the user types. Read live; of_reset puts it back to false |
ib_find_whole_word | boolean | false | Search option: finds the text only as a whole word (a letter, a digit or a _ next to it belongs to the word: id is found neither inside user_id nor inside ids). The ab toggle of the search box is the same switch. Read live; of_reset puts it back to false |
is_theme_style | string | "" | Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change |
is_theme_mode | string | "" | Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change |
il_theme_accent | long | -1 | Accent colour of this component (-1 = the application accent, or the theme's) |
is_tooltip | string | "" | Simple tooltip shown when hovering the component |
is_super_tooltip_title | string | "" | Title of the rich tooltip (takes precedence over is_tooltip) |
is_super_tooltip_text | string | "" | Text of the rich tooltip (rich markup accepted) |
is_super_tooltip_image | string | "" | Image of the rich tooltip |
Methods #
| Method | Description |
|---|---|
of_expand_all ( ) → long | Unfolds every container. No ue_node_toggled: no gesture opens the whole tree at once. Returns 0, -2 if the component is not created |
of_collapse_all ( ) → long | Folds every nested container (the top level stays visible). A selection hidden by a fold moves onto the folded block, and ue_selection_changed says so. No ue_node_toggled: no gesture folds the whole tree at once. Returns 0, -2 if the component is not created |
of_expand_path ( string as_path ) → long | Opens ONE block (an object or an array) by its path, and the blocks above it so it can be seen. Like its + marker, it raises ue_node_toggled for the block and for each folded block above it opened on the way (nothing for a block already open). Returns 0, -5 if no block has that path (unknown, or a leaf), -2 if the component is not created |
of_collapse_path ( string as_path ) → long | Folds ONE block by its path. Like its − marker, it raises ue_node_toggled when the block was open, and ue_selection_changed when the selection has to move onto it. Returns 0, -5 if no block has that path (unknown, or a leaf), -2 if the component is not created |
of_is_expanded ( string as_path ) → boolean | true when the block at that path is open, read LIVE; false when it is folded, and for a leaf or an unknown path. Enough to save what the user opened and restore it |
of_copy ( ) → long | Puts the selection on the clipboard, like Ctrl+C in the tree: a leaf gives its value DECODED (a string without quotes or escapes), a block its indented JSON text. Returns 0, -4 if nothing is selected, -2 if the component is not created |
of_clear ( ) → long | Empties the tree (like is_json = ""); ib_wrap, ib_search_enabled, ib_find_match_case and ib_find_whole_word keep their values (of_reset is the one that puts everything back). Returns 0, -2 if the component is not created |
of_expand_to_level ( long al_level ) → long | Shows the tree down to al_level: blocks at that depth or deeper fold shut (1 = the root block's direct children, 0 folds the root). No ue_node_toggled; a selection it moves onto a folded block raises ue_selection_changed. Returns 0, -2 if the component is not created |
of_search ( string as_query ) → long | Highlights every occurrence (case-insensitive by default — see ib_find_match_case —, whole words only with ib_find_whole_word; two on one line count two) and jumps to the first; only the blocks that hide the CURRENT occurrence open, and of_clear_search folds them back. ue_search_result says how many. The search looks in the text as SHOWN: an escaped character is searched escaped (C:\\Temp). An empty query is of_clear_search. The search box opens with the query in it and the focus on it (the same as Ctrl+F): Enter moves to the next; with ib_search_enabled false, the tree only highlights. Returns 0, or a negative code |
of_search_next ( ) → long | Moves to the NEXT occurrence (back to the first after the last); ue_search_result gives the new position. Returns 0, or a negative code |
of_search_prev ( ) → long | Moves to the PREVIOUS occurrence (back to the last before the first); ue_search_result gives the new position. Returns 0, or a negative code |
of_clear_search ( ) → long | Clears the search: no more highlights nor current occurrence (of_match_count returns 0), the search box empties and closes, and the blocks the search opened fold back as they were before it. Returns 0, or a negative code |
of_select_path ( string as_path ) → long | Selects and scrolls to the node at as_path; like the keyboard, it raises ue_selection_changed (nothing when the node is already selected); the folded blocks that hide it open. as_path is a path of n_pbt_json (lines/1/sku, "" = the root). Returns 0, -5 if no node has that path (the selection does not move), -2 if the component is not created |
of_selected_path ( ) → string | The path of the selected node, read LIVE: the path of n_pbt_json, levels joined by / and an array index counted from 1 (lines/1/sku), to hand as it is to of_get_string on the same text. A key that is empty or contains / cannot be addressed. "" is the root, or nothing selected: of_has_selection tells them apart |
of_selected_value ( ) → string | The JSON value of the selected line when it is a LEAF (a string keeps its quotes, ready to paste), read LIVE. Empty for a container, or with no selection |
of_selected_text ( ) → string | The VALUE of the selected leaf, decoded, read LIVE: a string without its quotes and escapes, a number or true/false/null as written. Empty for a container or without a selection |
of_has_selection ( ) → boolean | true when a node is selected, read LIVE — the root included, whose path is "" |
of_match_count ( ) → long | Returns how many OCCURRENCES the current search found (two on one line count two), read LIVE — the 12 of a 3 / 12 status line. 0 without a search |
of_match_index ( ) → long | Returns the 1-based position of the current match, read LIVE — the 3 of a 3 / 12 status line. 0 with no match |
Events #
| Event | When |
|---|---|
ue_node_clicked (string as_path) | The user clicked a node, or pressed Enter on a selected leaf: its path, the path of n_pbt_json (lines/1/sku, "" for the root) — of_get_string(as_path) on the same text reads its value. Enter on a block folds it, and never reaches the window's default button |
ue_node_toggled (string as_path, boolean ab_expanded) | A block was folded (ab_expanded = false) or opened (true): by the user (its + / − marker, the arrows, Enter or Space) or by of_expand_path / of_collapse_path. of_expand_all, of_collapse_all and of_expand_to_level do not raise it: no gesture folds the whole tree |
ue_selection_changed (string as_path) | The selection moved without a click, by the user or by your code: arrows, Home/End, Page Up/Down, of_select_path, or a fold that hides the selected line (the selection then moves onto the folded block) — a mouse click reports ue_node_clicked |
ue_search_result (long al_count, long al_index) | A search started or moved: al_count occurrences in all, the current one is al_index (1-based, 0 if none) — enough to show "3 / 12" |
ue_error (string as_message) | The text in is_json is not valid JSON: the message says why, with the line and the column, in the display language; the tree stays empty. Also raised for a document too large to be shown (more than 1,500,000 lines) |
Example #
Explore an API response #
// Fetch the order : the tree shows the response, or empties on a failure
if inv_rest.of_get(/*url*/ "https://api.example.com/orders/4152") = 200 then
uo_json.is_json = inv_rest.of_response_text()
uo_json.of_collapse_all() // the reader opens what interests them
else
uo_json.of_clear()
end if
Read the value of a clicked node #
// ue_node_clicked of uo_json : the path is the one n_pbt_json reads
n_pbt_json lnv_json
// Read the value at the clicked path with n_pbt_json
lnv_json.of_load(/*json*/ uo_json.is_json)
st_value.text = lnv_json.of_get_string(/*path*/ as_path)
// or, without a second parser : the value of the selected leaf, decoded
st_value.text = uo_json.of_selected_text()
Search whole words, case included #
// Whole words only, with the same case : "id" is not found inside "user_id"
uo_json.ib_find_match_case = true
uo_json.ib_find_whole_word = true
uo_json.of_search(/*query*/ "id")
Good practice #
- It is a viewer, not an editor: it shows the JSON, it does not change it. To read a value, hand the path of
ue_node_clickedton_pbt_json.of_get_stringon the same text, or readof_selected_text. - A big JSON stays fluid: only the lines on screen are drawn, a response of several hundred KB is browsed with the keyboard without waiting.
of_collapse_allfirst is still the most readable. - Invalid JSON breaks nothing:
ue_errorsays so (with the line and column of the fault), the tree stays empty. That is the feedback to show, not a crash. - A key that is empty or contains
/has no path:n_pbt_jsoncannot address it either. Two identical keys in one object are both shown; the path designates the first. - Right to left: a JSON document is a left-to-right text, and the tree stays so in an RTL application (only the search box follows the application's direction).
- The keyboard stays with the tree: Enter folds a block or "clicks" a leaf (
ue_node_clicked), never the window's default button; Escape first closes an open search box, then goes back to the window; the closing lines (},]) are not positions of the selection; Ctrl+C copies the selection (of_copy). - Very large documents: above 1,500,000 lines the document is refused with
ue_errorrather than silently cut. Printing (of_print,of_print_to_pdf) outputs the whole document, up to 10,000 lines.
Inherited from the common base #
These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.
| Members | Role | Detailed in |
|---|---|---|
of_reset | Put the component back to zero | 3.6 Resetting a component: of_reset() |
of_register_shortcut · of_clear_shortcuts | The component's keyboard chords | 3.5 Keyboard shortcuts |
of_is_created · of_is_ready · of_get_last_error | Whether it was born, whether it is ready, what failed | 3.7 Diagnostics |
of_save_as_png · of_save_as_jpg | Export the rendering as an image | 3.8 Exporting the rendering as an image |
of_set_redraw | Group changes into a single repaint | 3.10 Best practices |
of_preload_icons | Icons shown with no delay | Instant display: of_icon |
of_set_translation | Translate one of the component's labels | 5.2 Adapting a label: of_set_translation |
of_focus_webview | Give the component the focus | 6.4 Keyboard and focus |
of_print · of_print_to_pdf | Print, or write a PDF | 6.9 Printing |
of_set_property · of_get_property · of_component_name | Driving a property by its name | 3.1 The property engine |