@skaldapp/flat-json-tree

A Vue 3 composable that transforms JSON tree objects into flat arrays for easy manipulation with standard array operations while maintaining tree structure through computed properties
14,298
Install
npm install @skaldapp/flat-json-tree
Latest Version:2.3.23
Vue:3
License:AGPL-3.0-only
Last Updated:Oct 21, 2026
Links: npm
Maintainer: skaldapp

flat-json-tree

A dead simple way to manipulate JSON tree objects by transforming them into flat arrays for standard operations.

Overview

The core idea is to transform a JSON tree object into a flat array, allowing standard operations like find, findIndex, filter, map, and others. A mandatory requirement for the algorithm is that each element in the JSON tree must have a field with a unique identifier.

To preserve the tree structure and enable manipulations, the following computed properties are added to each child object:

{
  // Array of objects representing the path from root to current node
  branch: (Record < string, unknown > []);
  // Index of the object in the sibling array
  index: number;
  // Next object in the sibling array
  next: Record<string, unknown> | undefined;
  // Parent object
  parent: Record<string, unknown> | undefined;
  // Previous object in the sibling array
  prev: Record<string, unknown> | undefined;
  // Array of sibling objects
  siblings: (Record < string, unknown > []);
}

Installation

npm i @skaldapp/flat-json-tree

API

useFlatJsonTree(tree, options?)

The main composable function that transforms a JSON tree into a flat array with tree navigation properties.

Parameters:
  • tree (Required): Record<string, unknown>[] - The JSON tree object
  • options (Optional): Configuration object to define alternative names for id, children, and computed properties
    • branch: Property name for the branch path (default: "branch")
    • children: Property name for child nodes (default: "children")
    • id: Property name for unique identifiers (default: "id")
    • index: Property name for index in siblings (default: "index")
    • next: Property name for next sibling (default: "next")
    • parent: Property name for parent object (default: "parent")
    • prev: Property name for previous sibling (default: "prev")
    • siblings: Property name for siblings array (default: "siblings")
Returns:

An object with the following properties:

  • nodes: ComputedRef<Record<string, unknown>[]> - Computed flat array of objects
  • kvNodes: ComputedRef<{[id: string]: Record<string, unknown>}> - Reactive object with unique IDs as keys
  • Manipulation methods:
    • add(pId: string): Add an empty object to the siblings
    • addChild(pId: string): Add an empty object to the children
    • remove(pId: string): Remove an object from the tree
    • down(pId: string): Move an object down by one position
    • left(pId: string): Move an object left by one position
    • right(pId: string): Move an object right by one position
    • up(pId: string): Move an object up by one position

Usage

Assume we have a tree structure with elements like:

{ id: number, name: string, children: [] }

Elements can contain arbitrary fields, but must have a unique identifier.

Example using useFlatJsonTree composable

import useFlatJsonTree from "@skaldapp/flat-json-tree";

const tree = [
  {
    id: 1,
    name: "root",
    children: [
      {
        id: 2,
        name: "1.2",
        children: [
          { id: 5, name: "1.2.5" },
          { id: 6, name: "1.2.6" },
        ],
      },
      { id: 3, name: "1.3" },
      {
        id: 4,
        name: "1.4",
        children: [
          { id: 7, name: "1.4.7" },
          { id: 8, name: "1.4.8" },
          { id: 9, name: "1.4.9" },
        ],
      },
    ],
  },
];

const { nodes, kvNodes, add, down, left, remove, right, up } =
  useFlatJsonTree(tree);

Check the resulting flat array (using JSON.stringify to omit computed properties):

console.log(JSON.stringify(nodes.value));

The result is a flat array containing all objects. Keep in mind that each object has computed properties added: branch, index, next, parent, prev, and siblings

[
  {
    "id": 1,
    "name": "root",
    "children": [
      {
        "id": 2,
        "name": "1.2",
        "children": [
          { "id": 5, "name": "1.2.5" },
          { "id": 6, "name": "1.2.6" }
        ]
      },
      { "id": 3, "name": "1.3" },
      {
        "id": 4,
        "name": "1.4",
        "children": [
          { "id": 7, "name": "1.4.7" },
          { "id": 8, "name": "1.4.8" },
          { "id": 9, "name": "1.4.9" }
        ]
      }
    ]
  },
  {
    "id": 2,
    "name": "1.2",
    "children": [
      { "id": 5, "name": "1.2.5" },
      { "id": 6, "name": "1.2.6" }
    ]
  },
  { "id": 5, "name": "1.2.5" },
  { "id": 6, "name": "1.2.6" },
  { "id": 3, "name": "1.3" },
  {
    "id": 4,
    "name": "1.4",
    "children": [
      { "id": 7, "name": "1.4.7" },
      { "id": 8, "name": "1.4.8" },
      { "id": 9, "name": "1.4.9" }
    ]
  },
  { "id": 7, "name": "1.4.7" },
  { "id": 8, "name": "1.4.8" },
  { "id": 9, "name": "1.4.9" }
]

Now let's try to find the object named "1.2.6":

console.log(JSON.stringify(nodes.value.find(({ name }) => name === "1.2.6")));

Output:

{ "id": 6, "name": "1.2.6" }

If the ID is known, you can use kvNodes:

console.log(JSON.stringify(kvNodes.value[6]));

Output:

{ "id": 6, "name": "1.2.6" }

Now let's try using the computed properties. Suppose we need to find the parent element of the object named "1.2.6":

console.log(
  JSON.stringify(nodes.value.find(({ name }) => name === "1.2.6").parent),
);

The result is the object named "1.2", which is the parent element of the object named "1.2.6":

{
  "id": 2,
  "name": "1.2",
  "children": [
    { "id": 5, "name": "1.2.5" },
    { "id": 6, "name": "1.2.6" }
  ]
}

Now let's add the object { id: 10, name: "1.2.10" } to the tree after the object named "1.2.6":

// Find the object named "1.2.6"
const curObject = nodes.value.find(({ name }) => name === "1.2.6");
// Add the object { id: 10, name: "1.2.10" }
curObject.siblings.splice(curObject.index + 1, 0, { id: 10, name: "1.2.10" });
// Output the tree object passed to the useFlatJsonTree composable
console.log(JSON.stringify(tree));

Output:

[
  {
    "id": 1,
    "name": "root",
    "children": [
      {
        "id": 2,
        "name": "1.2",
        "children": [
          { "id": 5, "name": "1.2.5" },
          { "id": 6, "name": "1.2.6" },
          { "id": 10, "name": "1.2.10" }
        ]
      },
      { "id": 3, "name": "1.3" },
      {
        "id": 4,
        "name": "1.4",
        "children": [
          { "id": 7, "name": "1.4.7" },
          { "id": 8, "name": "1.4.8" },
          { "id": 9, "name": "1.4.9" }
        ]
      }
    ]
  }
]

Finally, let's test the service function. Move the object named "1.2.6" to the position before "1.2.5":

// Find the object named "1.2.6"
const curObject = nodes.value.find(({ name }) => name === "1.2.6");
// Use the service function up to move it
up(curObject.id);
// Output the tree object passed to the useFlatJsonTree composable
console.log(JSON.stringify(tree));

As a result, the objects named "1.2.5" and "1.2.6" have swapped positions:

[
  {
    "id": 1,
    "name": "root",
    "children": [
      {
        "id": 2,
        "name": "1.2",
        "children": [
          { "id": 6, "name": "1.2.6" },
          { "id": 5, "name": "1.2.5" }
        ]
      },
      { "id": 3, "name": "1.3" },
      {
        "id": 4,
        "name": "1.4",
        "children": [
          { "id": 7, "name": "1.4.7" },
          { "id": 8, "name": "1.4.8" },
          { "id": 9, "name": "1.4.9" }
        ]
      }
    ]
  }
]

License

This project is licensed under the AGPL-3.0-only license.

Made on the shores of the Baltic Sea 🚢

Related Packages

vue-json-tree

Vue component that renders JSON data in a collapsible tree structure.

141,887 50
json-tree-view-vue3

JSON tree rendering Vue3 component

110,063 39
vue3-org-chart

Vue3 Org Chart is a tree diagram that visualizes the structure of an organizatio...

25,215 33
vue-dd

Vue.js component for displaying JavaScript objects with circular references, for...

17,539 17
@moonwane/vue3-org-chart

Forked from n1crack/vue3-org-chart. Vue3 Org Chart is a tree diagram that visual...

3,672 1

Version History

Version Released License
2.3.23 AGPL-3.0-only
2.3.22 AGPL-3.0-only
2.3.21 AGPL-3.0-only
2.3.20 AGPL-3.0-only
2.3.19 AGPL-3.0-only