Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,25 @@ console.log(omitEmpty({ a: ['a'], b: [] }));
console.log(omitEmpty({ a: 0, b: 1 }));
//=> { a: 0, b: 1 }

## Options
When calling `omitEmpty`, you can pass options to control behavior:

| Option key | default | description |
|---|---|---|
|omitZero|false| When set to `true` causes any properties with a value of 0 to be removed|
|omitEmptyArray|true| When set to `false` empty arrays will be preserved|
|excludeProperties| | Specify a list of string properties that will be skipped. If the property is an object, then the value will not be recursed (meaning, omit-empty is not run on the nested object.|

Examples:

```js
// set omitZero to true, to evaluate "0" as falsey
console.log(omitEmpty({ a: 0, b: 1 }, { omitZero: true }));
//=> { b: 1 }
```



## About

<details>
Expand Down
48 changes: 32 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,50 @@

const typeOf = require('kind-of');

const omitEmpty = (obj, options) => {
let omitZero = options ? options.omitZero : false;
const omitEmpty = (obj, options = {}) => {
const runtimeOpts = _buildRuntimeOpts(options);

let omit = value => {
let omit = (value, opts) => {
if (Array.isArray(value)) {
value = value.map(v => omit(v)).filter(v => !isEmpty(v, omitZero));
value = value.map(v => omit(v, opts)).filter(v => !isEmpty(v, opts));
}

if (typeOf(value) === 'object') {
let result = {};
for (let key of Object.keys(value)) {
let val = omit(value[key]);
if (val !== void 0) {
result[key] = val;
if (opts.excludeProperties.includes(key)) {
result[key] = value[key];
} else {
let val = omit(value[key], opts);
if (val !== void 0) {
result[key] = val;
}
}
}
value = result;
}

if (!isEmpty(value, omitZero)) {
if (!isEmpty(value, opts)) {
return value;
}
};

let res = omit(obj);
let res = omit(obj, runtimeOpts);
if (res === void 0) {
return typeOf(obj) === 'object' ? {} : res;
}
return res;
};

function isEmpty(value, omitZero) {
function _buildRuntimeOpts(options = {}) {
return {
omitZero: options.omitZero || false,
omitEmptyArray: options.omitEmptyArray === false ? false : true,
excludeProperties: options.excludeProperties || []
};
};

function isEmpty(value, runtimeOpts) {
switch (typeOf(value)) {
case 'null':
case 'undefined':
Expand All @@ -51,19 +63,23 @@ function isEmpty(value, omitZero) {
case 'set':
return value.size === 0;
case 'number':
return omitZero ? value === 0 : false;
return runtimeOpts.omitZero ? value === 0 : false;
case 'error':
return value.message === '';
case 'array':
for (let ele of value) {
if (!isEmpty(ele, omitZero)) {
return false;
if (runtimeOpts.omitEmptyArray) {
for (let ele of value) {
if (!isEmpty(ele, runtimeOpts)) {
return false;
}
}
return true;
} else {
return false;
}
return true;
case 'object':
for (let key of Object.keys(value)) {
if (!isEmpty(value[key], omitZero)) {
if (!isEmpty(value[key], runtimeOpts)) {
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "omit-empty",
"description": "Recursively omit empty properties from an object. Omits empty objects, arrays, strings or zero.",
"version": "1.0.0",
"version": "1.1.0",
"homepage": "https://github.com/jonschlinkert/omit-empty",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"repository": "jonschlinkert/omit-empty",
Expand Down
39 changes: 34 additions & 5 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ describe('omit-empty', () => {
assert.deepEqual(omitEmpty(['foo']), ['foo']);
});

it('should return empty arrays with option config', () => {
assert.deepEqual(omitEmpty(['foo'], { omitEmptyArray: false }), ['foo']);
});


it('should return undefined when the value is an empty string', () => {
assert.equal(omitEmpty(''), void 0);
});
Expand Down Expand Up @@ -60,9 +65,9 @@ describe('omit-empty', () => {
});

it('should omit nested empty objects.', () => {
assert.deepEqual(omitEmpty({ a: { b: undefined, c: 'd' } }), { a: { c: 'd' }});
assert.deepEqual(omitEmpty({ a: { b: null, c: 'd' } }), { a: { c: 'd' }});
assert.deepEqual(omitEmpty({ a: { b: '', c: 'd' } }), { a: { c: 'd' }});
assert.deepEqual(omitEmpty({ a: { b: undefined, c: 'd' } }), { a: { c: 'd' } });
assert.deepEqual(omitEmpty({ a: { b: null, c: 'd' } }), { a: { c: 'd' } });
assert.deepEqual(omitEmpty({ a: { b: '', c: 'd' } }), { a: { c: 'd' } });
});

it('should deeply omit nested empty objects.', () => {
Expand All @@ -72,8 +77,8 @@ describe('omit-empty', () => {
});

it('should not omit functions', () => {
let fn = (a, b, c) => {};
let fn2 = () => {};
let fn = (a, b, c) => { };
let fn2 = () => { };
assert.deepEqual(omitEmpty({ a: fn, b: fn2 }), { a: fn, b: fn2 });
});

Expand Down Expand Up @@ -147,4 +152,28 @@ describe('omit-empty', () => {
}
});
});

it('should omit deeply nested values with Config options', () => {
let o = {
a: {
b: { c: 'foo', d: 0, e: { f: { g: {}, h: { i: 'i' } } } },
foo: [['bar', 'baz'], []],
bar: [],
one: 1,
two: 2,
three: 0
}
};

assert.deepEqual(omitEmpty(o, { omitEmptyArray: false, omitZero: true, excludeProperties: ['three'] }), {
a: {
b: { c: 'foo', e: { f: { h: { i: 'i' } } } },
foo: [['bar', 'baz'], []],
bar: [],
one: 1,
two: 2,
three: 0
}
});
});
});