Skip to content

JavaScript Object Filter. Deep filtering key/content recursively. Support wildcard, nested, and filter function in template.

License

Notifications You must be signed in to change notification settings

bluet/obj-filter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build CodeQL Node CI FOSSA Status

Quality Gate Status Open Source Helpers
npm version install size npm downloads GitHub license

obj-filter - JavaScript Object Filter / Merger.

JavaScript Object Filter. Deep filtering key/content recursively.
Support type checking, wildcard, nested, and filter function in template.

INSTALL

npm i obj-filter

Or find help from:

SYNOPSIS

"use strict";

const {filter, merge, exist, ArrayIter} = require('obj-filter');

const template = {
    "runtime": {
        "connectionState": undefined,   // excluded
        "powerState": function (args) {return "HELLO WORLD " + args},   // pass into the checker function
        "bootTime": "my boot time",     // included
        "paused": false,
        "snapshotInBackground": 1111111,
        "numbers": ArrayIter(filter, Number),   // value of "numbers" must be an array, and will check all elements in the array
    },
    "running": Boolean
};

let clean_data = filter( template, fetchData() );
let updated_data = filter.merge( clean_data, newUpdates() );
let clean_full_data = filter.exist( template, fetchData() );

Template Object

According to the Template Object structure, obj-filter supports the following types of value with different behaviors to build the result object.

undefined

If the value of the key is undefined, the key will be filtered (skipped) and will not included in result object.

object

If the value of the key is an object, obj-filter will dive into it and check the deeper level of keys.

function

If the value of the key is an function, obj-filter will pass the value of the same key in input data to the function, and includes it's returned data in result.
So it's your call to customize how you would like to handle, define what you want to do with the input data. Be sure to return something from your function.

  • If return undefined, the key will be filtered (skipped).
  • If return anything else, the key will be included.

DataTypes / Constructors

String, Number, Boolean, Array, Symbol, Map, Set, WeakMap, WeakSet, Object, Function in template will do type checking on target object.

Success if type matches and fails if they don't.

Anything else (string, array, number, etc)

The value of the key will be included.

onException callback function

You can pass an additional onException callback function into filter(), filter.merge(), and filter.exist() to handle exceptions.

onException(template, input, error_msg) will be called when data expected but type mismatch or undefined.

filter(template, data, (tpl, obj, err) => { console.dir({tpl, obj, err}); return undefined; });

ArrayIter Check Array Elements

If you want to check values of array, use ArrayIter. It makes sure that value must be an Array and checks all elements in the array.

The first two arguments are required:

  • (required) filter / merge / exist
  • (required) template
  • (optional) option
    • min: an Integer, default 0. indicates at least how many elements must be valid. If the result array contains elements fewer than that number, the whole result will be undefined.
    • onException: a Function, will be called when exception occurred.
const template = {
	"a1": ArrayIter(filter, {
		"a": String,
		"a11": ArrayIter(
            exist,
            Number,
            {"onException": () => undefined}
        ),
		"a12": ArrayIter(merge, {
			"a121": filter.ArrayIter(filter, Number, {"min": 3})
		}),
	}),
	"a2": ArrayIter(filter, Number)
};

Default Function

Keep only wanted data

When fetching data through API, sometimes the returned data could be Huge. You need many of them, but there are also too many trash included in returned data.
Copying with result[xxx] = input[xxx]; each by each, line by line, is a hell.
Now you can copy one returned data structure (in JSON) to your favorite text editor, delete all unwanted lines, paste it back to your code, and use it as template.

"use strict";

var filter = require('obj-filter');

var template = {
    "runtime": {
        "connectionState": undefined,       // In Template, when the value is undefined, the key will be ignored.
        "powerState": function (args) {return "HELLO WORLD " + args},    // pass data into your function, and use it as result value
        "bootTime": "my boot time",         // The string is just for your own note. Will keep whatever input is in result.
        "paused": false,                    // Will keep whatever input is in result.
        "snapshotInBackground": 1111111     // Will keep whatever input is in result.
    }
};

var data = function_or_somewhere();

// Assume:
// var data = {
//    "vm": {
//        "type": "VirtualMachine"
//    },
//    "runtime": {
//        "device": 9999,
//        "connectionState": "connected",
//        "powerState": "poweredOn",
//        "bootTime": "2017-04-20T13:56:19.377Z",
//        "paused": false,
//        "snapshotInBackground": true
//    }
//};


var clean_data = filter(template, data);

// clean_data is:
{
    "runtime": {
        "powerState": "HELLO WORLD poweredOn",
        "bootTime": "2017-04-20T13:56:19.377Z",
        "paused": false,
        "snapshotInBackground": true
    }
};

User Data Checks

Validate user input data in browser (before send to server), or check them at server-side.

var template = {
    email: validateEmail(email),                // call function validateEmail and use it's return value as value
    username: function (username) {
        if (/^[a-zA-Z_]+$/.test(username)) {    // check if username contains only a-z or underscore
            return username;
        } else {
            throw new Error('Invalid username');
        }
    },
    password: "original password"               // keep whatever user inputs
}

save_or_send( filter(template, inputData) );

Separated template file

You can save template into separated files.

Say data_template/vmInfo.js

{
    "runtime": {
        "connectionState": undefined,
        "powerState": function (args) {return "HELLO WORLD " + args},
        "bootTime": "my boot time",
        "paused": false,
        "snapshotInBackground": 1111111
    }
};

Require it as template

var vm_tpl = require('data_template/vmInfo.js');

var vmData = filter(vm_tpl, yourData)

merge Function

Keep template keys when not provided in input data.

"use strict";

var filter = require('obj-filter');

var template = {
    "runtime": {
        "connectionState": undefined,
        "powerState": function (args) {return "HELLO WORLD " + args},
        "CoffeeTeaOrMe": "Me"
    }
};

var newUpdates = fetchChanges();

// Assume:
// var newUpdates = {
//    "runtime": {
//        "connectionState": "connected",
//        "powerState": "poweredOn"
//    }
//};


var updated_data = filter.merge(template, newUpdates);

// updated_data is:
{
    "runtime": {
        "powerState": "HELLO WORLD poweredOn",
        "bootTime": "2017-04-20T13:56:19.377Z",
        "CoffeeTeaOrMe": "Me"
   }
};

exist Function

Similar to default filter, but All Keys in template must also exists in input data.

"use strict";

var filter = require('obj-filter');

var template = {
	"vm": undefined,
	"runtime": {
		"connectionState": undefined,
		"powerState": function (args) {return "HELLO WORLD " + args},
		"bootTime": "my boot time",
		"obj jj": { "kk": "yy" }
	}
};

var data = fetch_from_somewhere();

// Assume:
// var data = {
// 	"runtime": {
// 		"device": 9999,
// 		"connectionState": "connected",
// 		"powerState": "poweredOn",
// 		"bootTime": 2,
// 		"obj jj": { "kk": "zz" }
// 	}
// };


var clean_full_data = filter.exist(template, data);

// clean_full_data is:
{
	"runtime": {
		"powerState": "HELLO WORLD poweredOn",
		"bootTime": 2,
		"obj jj": { "kk": "zz" }
	}
};

Contribute

PRs welcome!
If you use/like this module, please don't hesitate to give me a Star. I'll be happy whole day!

Hope this module can save your time, a tree, and a kitten.

License

FOSSA Status

About

JavaScript Object Filter. Deep filtering key/content recursively. Support wildcard, nested, and filter function in template.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published