Floppy Filter
Just another library to filter JavaScript objects, based on a simple and flexible pattern with support for negation.
Installation
npm install floppy-filter --save
Features
-
Wildcard Matching:
*
can be used with.
to select different paths within an object. -
Negation:
!
can be used with*
to allow all properties except negated paths within an object. -
Explicit: Selecting
user.address
does not show address object and its nested properties butuser.address.city
will selectaddress
object withcity
property, oruser.address.*
to selectaddress
object and all its primitive properties
Primitive Properties: Properties with values that are not Objects
Usage
We will use this sample object to apply library functionalities
const user = {
"_id": "5f13c2e046d4e1b898cd25c5",
"index": 0,
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
"isActive": true,
"balance": "$3,848.78",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "blue",
"name": {
"first": "Callahan",
"last": "Gilliam"
},
"address": {
"country": "Philippines",
"city": "Baliuag Nuevo",
"street": "82 Roxbury Drive",
"location": {
"lat": 13.5201065,
"lng": 123.1985807
}
},
"company": "OLYMPIX",
"email": "callahan.gilliam@olympix.info",
"phone": "+1 (845) 441-3694",
"about": "Ullamco irure est dolor non culpa consequat.",
"registered": "Sunday, March 15, 2015 2:07 AM",
"latitude": "-14.770193",
"longitude": "54.884539",
"tags": ["ullamco", "amet", "enim", "id", "fugiat"],
"range": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
"friends": [
{
"id": 0,
"name": "Corine Mcleod"
},
{
"id": 1,
"name": "Lauri Fields"
},
{
"id": 2,
"name": "Jami Cortez"
}
],
"greeting": "Hello, Callahan! You have 8 unread messages.",
"favoriteFruit": "apple"
}
Select Subset
Select one or more properties
filterObject(user, ['_id', 'guid']);
// Output
{
"_id": "5f13c2e046d4e1b898cd25c5",
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923"
}
Select from nested properties
filterObject(user, ['_id', 'guid', 'address.city']);
// Output
{
"_id": "5f13c2e046d4e1b898cd25c5",
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
"address": {
"city": "Baliuag Nuevo"
}
}
We can select all nested properties using
*
operator, But this will only select first level ofaddress
object which contains only (country
,city
,street
) properties, but not thelocation
attribute as its an object not primitive.
Here is an example:
filterObject(user, ['_id', 'guid', 'address.*']);
// Output
{
"_id": "5f13c2e046d4e1b898cd25c5",
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
"address": {
"country": "Philippines",
"city": "Baliuag Nuevo",
"street": "82 Roxbury Drive"
}
}
To select all nested properties (including objects) in address
object, We need to use **
which will select all nested paths inside object
filterObject(user, ['_id', 'guid', 'address.**']);
// Output
{
"_id": "5f13c2e046d4e1b898cd25c5",
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
"address": {
"country": "Philippines",
"city": "Baliuag Nuevo",
"street": "82 Roxbury Drive",
"location": {
"lat": 13.5201065,
"lng": 123.1985807
}
}
}
Select Subset from an Array
We can select at a specific index of an array using
-
array.i.attr
Select specific properties within specific item, Exuser.friends.0.id
-
array.i.*
Select whole item primitive properties (Without Objects) , Exuser.friends.0.*
-
array.i.**
Select whole item wit all nested properties, Exuser.friends.0.**
Using
array.0
will not return the item at index0
You must explicitly select specific attribute likefriends.0.id
, select all using*
likefriends.0.*
orfriends.0.**
filterObject(user, ['_id', 'guid', 'friends.0.id']);
// Output
{
"_id": "5f13c2e046d4e1b898cd25c5",
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
"friends": [
{
"id": 0
}
]
}
filterObject(user, ['_id', 'guid', 'friends.0.*']);
// Output
{
"_id": "5f13c2e046d4e1b898cd25c5",
"guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
"friends": [
{
"id": 0,
"name": "Corine Mcleod"
}
]
}
Negation
Select all properties, without _id
and guid
properties
filterObject(user, ['*', '!_id', '!guid']);
// Output
{
"index": 0,
"isActive": true,
"balance": "$3,848.78",
"picture": "http://placehold.it/32x32",
...
}
Select all properties, without address.country
property
filterObject(user, ['*', '!address.country']);
// Output
{
...,
"address": {
"city": "Baliuag Nuevo",
"street": "82 Roxbury Drive",
"location": {
"lat": 13.5201065,
"lng": 123.1985807
}
},
...
}
Filter object with negation like
['*', '!address']
to filter outaddress
object will not work, you should explicitly specify insideaddress
object, like using:
['*', '!address.country']
to filter outcountry
property['*', '!address.*']
to filter out all primitive properties (country
,city
,street
)['*', '!address.**']
to filter out the wholeaddress
object
Select all properties, but filter out id
property from first object inside friends
array
filterObject(user, ['*', '!friends.0.id']);
// Output
{
...,
"friends": [
{
"name": "Corine Mcleod"
},
{
"id": 1,
"name": "Lauri Fields"
},
{
"id": 2,
"name": "Jami Cortez"
}
],
...
}
Select all properties, but filter out id
property from all nested objects inside friends
array
filterObject(user, ['*', '!friends.*.id']);
// Output
{
...,
"friends": [
{
"name": "Corine Mcleod"
},
{
"name": "Lauri Fields"
},
{
"name": "Jami Cortez"
}
],
...
}
Select all properties, but filter out first object inside friends
array
filterObject(user, ['*', '!friends.0.*']);
// Output
{
...,
"friends": [
{
"id": 1,
"name": "Lauri Fields"
},
{
"id": 2,
"name": "Jami Cortez"
}
],
...
}
Interesting use cases
Combining *
, selection patterns and negation patterns makes it very flexible to filter JavaScript objects
You can select all primitive properties using these filters ['*', '!**.**']
const user = {
"name": "John",
"age": 24,
"address": {
"country": "Indonesia",
"city": "Gombong",
"street": "81 Upham Lane",
"location": {
"lat": -7.6052823,
"lng": 109.5151561
}
},
"phones": ["+1 (881) 402-2942", "+1 (881) 402-2946"]
};
const filter = ['*', '!**.**'];
const result = filterObject(user, filter);
console.log(result);
The result:
{
"name": "John",
"age": 24
}
Or do the opposite and select only objects and ignore primitive properties using these filters ['*', '!*']
and the result will be:
{
"address": {
"country": "Indonesia",
"city": "Gombong",
"street": "81 Upham Lane",
"location": {
"lat": -7.6052823,
"lng": 109.5151561
}
},
"phones": ["+1 (881) 402-2942", "+1 (881) 402-2946"]
}
Patterns
Pattern (Sample) | Description |
---|---|
* |
Select all properties in object, including all nested object, arrays (All depth levels, clone original object) |
user.* |
Inside user object, select all primitive properties (No Objects) |
user.*.name |
Inside user object, select "name" property within nested objects (first depth level) |
user.** |
Inside user object, select all nested objects and arrays (All depth levels) |
user.**.name |
Inside user object, select all objects with "name" property (All depth levels) |
*.name |
Select all objects with "name" property (first depth level) within root object |
**.name |
Select all objects with "name" property in all nested objects (All depth levels) within root object |
All previous patterns can be used with negation operator
!
License MIT