SkillAgentSearch skills...

Treeize

Converts row data (in JSON/associative array format) to tree structure based on column naming conventions.

Install / Use

/learn @kwhitley/Treeize
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Treeize.js

Build Status via Travis CI

Converts row data (in JSON/associative array format or flat array format) to object/tree structure based on simple column naming conventions.

Installation

npm install treeize

Why?

Because APIs usually require data in a deep object graph/collection form, but SQL results (especially heavily joined data), excel, csv, and other flat data sources that we're often forced to drive our applications from represent data in a very "flat" way. Treeize takes this flattened data and based on simple column/attribute naming conventions, remaps it into a deep object graph - all without the overhead/hassle of hydrating a traditional ORM.

What it does...

// Treeize turns flat associative data (as from SQL queries) like this:
var peopleData = [
  {
    'name': 'John Doe',
    'age': 34,
    'pets:name': 'Rex',
    'pets:type': 'dog',
    'pets:toys:type': 'bone'
  },
  {
    'name': 'John Doe',
    'age': 34,
    'pets:name': 'Rex',
    'pets:type': 'dog',
    'pets:toys:type': 'ball'
  },
  {
    'name': 'Mary Jane',
    'age': 19,
    'pets:name': 'Mittens',
    'pets:type': 'kitten',
    'pets:toys:type': 'yarn'
  },
  {
    'name': 'Mary Jane',
    'age': 19,
    'pets:name': 'Fluffy',
    'pets:type': 'cat'
  }
];


// ...or flat array-of-values data (as from CSV/excel) like this:
var peopleData = [
  ['name', 'age', 'pets:name', 'pets:type', 'pets:toys:type'], // header row
  ['John Doe', 34, 'Rex', 'dog', 'bone'],
  ['John Doe', 34, 'Rex', 'dog', 'ball'],
  ['Mary Jane', 19, 'Mittens', 'kitten', 'yarn'],
  ['Mary Jane', 19, 'Fluffy', 'cat', null]
];


// ...via a dead-simple implementation:
var Treeize   = require('treeize');
var people    = new Treeize();

people.grow(peopleData);


// ...into deep API-ready object graphs like this:
people.getData() == [
  {
    name: 'John Doe',
    age: 34,
    pets: [
      {
        name: 'Rex',
        type: 'dog',
        toys: [
          { type: 'bone' },
          { type: 'ball' }
        ]
      }
    ]
  },
  {
    name: 'Mary Jane',
    age: 19,
    pets: [
      {
        name: 'Mittens',
        type: 'kitten',
        toys: [
          { type: 'yarn' }
        ]
      },
      {
        name: 'Fluffy',
        type: 'cat'
      }
    ]
  }
];

API Index

1. get/set options (optional)
2a. set data signature manually if needed (optional)
2b. grow tree from data set(s)
3. retrieve transformed data
* misc/internal methods
  • getStats() - returns object with growth statistics

API

.options([options])<a name="options" />

Getter/Setter for options. If options object is passed, this is identical to .setOptions(options) and returns self (chainable). If no options are passed, this is identical to .getOptions() and returns current options as object.

.setOptions(options)<a name="setOptions" />

Sets options globally for the Treeize instance. This is an alias for .options(options). Default options are as follows:

{
  input: {
    delimiter:          ':',    // delimiter between path segments, defaults to ':'
    detectCollections:  true,   // when true, plural path segments become collections
    uniformRows:        false,  // set to true if each row has identical signatures
  },
  output: {
    prune:              true,   // remove blank/null values and empty nodes
    objectOverwrite:    true,   // incoming objects will overwrite placeholder ids
    resultsAsObject:    false,  // root structure defaults to array (instead of object)
  }
}

For example, to change the delimiter and enable output logging, you would use the following:

.setOptions({ input: { delimiter: '|' }});

Available Options

input.delimiter<a name="optionsInputDelimiter" /> This sets the delimiter to be used between path segments (e.g. the ":" in "children:mother:name"). View test example

input.detectCollections<a name="optionsInputDetectCollections" /> Enables/disables the default behavior of turning plural path segments (e.g. "subjects" vs. "subject") into collections instead of object paths. Note: In order to properly merge multiple rows into the same collection item, the collection must have a base-level attribute(s) acting as a signature. View test example (enabled) | or (disabled)

input.uniformRows<a name="optionsInputUniformRows" /> By default row uniformity is disabled to allow the most flexible data merging. This means each and every row of data that is processed (unless flat array-of-array data) will be analyzed and mapped individually into the final structure. If your data rows have uniform attributes/columns, disable this for a performance increase.

output.prune<a name="optionsOutputPrune" /> Removes blank/empty nodes in the structure. This is enabled by default to prevent sparse data sets from injecting blanks and nulls everywhere in your final output. If nulls are important to preserve, disable this. View test example

output.objectOverwrite<a name="optionsOutputObjectOverwrite" /> To allow for merging objects directly onto existing placeholder values (e.g. foreign key ids), this is enabled by default. View test example

output.resultsAsObject<a name="optionsOutputResultsAsObject" /> This creates a single root object (instead of the default array of objects). View test example

.getOptions()<a name="getOptions" />

Returns the current global options (as object). View example format

.resetOptions(options)<a name="resetOptions" />

Resets all global options to original defaults and returns self (chainable).

.signature([row], [options])<a name="signature" />

Getter/Setter for row signatures. If options object is passed, this is identical to .setSignature(options) and returns self (chainable). If no options are passed, this is identical to .getSignature() and returns currently defined signature as object.

.setSignature(row, [options])<a name="setSignature" />

Manually defines the signature for upcoming data sets from argument row, with optional options. The row may be either in object (key/value) form or flat array form (array of paths). This method is only required if sharing a single signature across multiple data sources (when merging homogeneous data sets), or when the data itself has no header information (for instance, with bulk flat array-of-values data). Returns self (chainable).

// May be set from a single row of associative data
.setSignature({
  'id': 1,
  'name:first': 'Kevin',
  'name:last': 'Whitley',
  'hobbies:name': 'photography'
  'hobbies:years': 12
})

// Or from header row of flat array data
.setSignature(['id', 'name:first', 'name:last', 'hobbies:name', 'hobbies:years'])

.getSignature()<a name="getSignature" />

Returns currently defined signature. For internal use only.

.clearSignature()<a name="clearSignature" />

Clears currently-defined signature if previously set via setSignature(row), and returns self (chainable). This is only required between data sets if signature auto-detection should be re-enabled. It is unlikely that you will need to use this.

.getData()<a name="getData" />

Returns current data tree.

var tree = new Treeize();

tree.grow([
  { 'foo': 'bar', 'logs:a': 1 },
  { 'foo': 'bar', 'logs:a': 2 },
  { 'foo': 'baz', 'logs:a': 3 },
]);

console.log(tree.getData());

/*
[
  { foo: 'bar', logs: [{ a: 1 }, { a: 2 }] },
  { foo: 'baz', logs: [{ a: 3 }]}
]
*/

.getSeedData()<a name="getSeedData" />

Returns original, flat data.

var tree = new Treeize();

tree.grow([
  { 'foo': 'bar', 'logs:a': 1 },
  { 'foo': 'bar', 'logs:a': 2 },
  { 'foo': 'baz', 'logs:a': 3 }
]);

console.log(tree.getSeedData());

/*
[
  { 'foo': 'bar', 'logs:a': 1 },
  { 'foo': 'bar', 'logs:a': 2 },
  { 'foo': 'baz', 'logs:a': 3 }
]
*/

.getStats()<a name="getStats" />

Returns current growth statistics (e.g. number of sources process, number of rows, etc). Output and format subject to change - use at your own risk.


.grow(data, [options])<a name="grow" />

The grow(data, [options]) method provides the core functionality of Treeize. This method expands flat data (of one or more sources) into the final deep

View on GitHub
GitHub Stars191
CategoryDevelopment
Updated14d ago
Forks23

Languages

JavaScript

Security Score

95/100

Audited on Mar 24, 2026

No findings