Overview
This article presents a case for using Jsonpath to traverse hierarchical structures. Vue.js is used for the demonstration. As an example, a reusable component is presented that can be configured to pick specific attributes at each desired level.
TLDR
Here is a component that can generate a set of cascading dropdowns. One can configure this component with a hierarchical JSON object and provide a set of expressions that the component will use to pull specific values from each level of the hierarchy to populate the dropdowns.
When would one need to traverse a hierarchical object tree?
There are numerous cases where information is organized in a tree form, such as folders (with several levels of sub folders) on a computer, organizational trees of managers and employees in a company, etc. One might need to drill down from the root of the tree down to a particular leaf. If a user wants to find the folder structure of a particular file, for example, the user can drill down through specific folders and their subfolders to arrive at a file.
Presenting the information in a manageable manner
Controls that limit the amount of information presented while aiding the user with the traversal, via a set of UI controls are quite a common occurrence.
There are several approaches for a problem like this. One can explicitly write code that refers to the attributes in the payload. An alternate approach is to use a recursive component that walks the tree. Here we provide a mechanism where the developer has the freedom to specify the number of levels of the tree that should be considered and what data from each level should be presented as possible choices in the dropdowns.
Why use JSONPath?
JSONPath provides for JSON what xpath provides for xml. Learn about JSONPath here(https://goessner.net/articles/JsonPath/). It enables a developer to write an expression that traverses a JSON object.
For an example payload as just shown, we would like a set of dropdowns to show as follows:
From the perspective of a developer who would use such a component, the input that would need to be specified would include
- The hierarchical data as an object,
- An array of JSON paths that describe how the payload should be retrieved from each level and
- A handler function that gets invoked upon every user selection.
The logic of traversing the tree till the appropriate level is handled by the component and driven by the input the developer provides.
Here is what the user of this component may have to write:
<cascadedropdown
:node=”treeData” :depth=”0″ v-bind:path=”{}” v-on:change-path=”handleNewPath” v-bind:jp=”[ ‘$.children[*].label’,’$.children[?(@.label==SELECTED1)].children[*].label’,
‘$.children[?(@.label==SELECTED1)].children[ (@.label==SELECTED2)].children[*].label’, ‘$.children[?(@.label==SELECTED1)].children[?(@.label==SELECTED2)].children[?(@.label==SELECTED3)].children[*].label’,]”>
</cascadedropdown>
Selected path: {{path}}
The payload to traverse is indicated by treeData. Depth is the initial depth of the traversal and it is initialized to 0. Path is used to collect the output of the user selection events. In this example, we accumulate the selection at each level as key value pairs of depth and selection at each level. handleNewPath is a function to handle the event that is fired when the user makes a selection. The jp variable contains an array of json paths that are evaluated at the appropriate level and the chosen labels are gathered to populate the dropdown. The SELECTED set of placeholders serve to gather the user selections as choices are made and to help filter the choices in subsequent dropdowns.
The mapping of JSONPath expressions to the drop downs is as follows:
The code assumes that the hierarchical payload (tree in this case) contains a label attribute of type string and an attribute called children that could contain 0 or more objects (of a similar layout of label etc.)
jayesh@ytp
May 14, 2024This is a very informative article, thanks for sharing.