PBToolboxAI v4 ← Site

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 raises ue_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 #

Userobjectu_pbt_jsontree
InputThe JSON text, in is_json (a string)
Fold / unfoldEach 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)
FeedbackA click on a node gives its path (ue_node_clicked), the path of n_pbt_json: lines/1/sku; invalid JSON raises ue_error
FaithfulEvery 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 #

PropertyTypeDefaultDescription
is_jsonstring""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_wrapbooleantrueLong lines wrap (true, the default) or stay on one line with a horizontal scrollbar (false) — a code-editor feel
ib_search_enabledbooleantrueCtrl+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_casebooleanfalseSearch 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_wordbooleanfalseSearch 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_stylestring""Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_modestring""Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accentlong-1Accent colour of this component (-1 = the application accent, or the theme's)
is_tooltipstring""Simple tooltip shown when hovering the component
is_super_tooltip_titlestring""Title of the rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Text of the rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of the rich tooltip

Methods #

MethodDescription
of_expand_all ( ) → longUnfolds 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 ( ) → longFolds 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 ) → longOpens 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 ) → longFolds 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 ) → booleantrue 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 ( ) → longPuts 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 ( ) → longEmpties 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 ) → longShows 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 ) → longHighlights 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 ( ) → longMoves 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 ( ) → longMoves 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 ( ) → longClears 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 ) → longSelects 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 ( ) → stringThe 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 ( ) → stringThe 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 ( ) → stringThe 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 ( ) → booleantrue when a node is selected, read LIVE — the root included, whose path is ""
of_match_count ( ) → longReturns 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 ( ) → longReturns the 1-based position of the current match, read LIVE — the 3 of a 3 / 12 status line. 0 with no match

Events #

EventWhen
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 #


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.

MembersRoleDetailed in
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine

← Component reference · Guide contents