【问题标题】:Remove empty & null values from nested object (ES6) - Clean nested Objects从嵌套对象(ES6)中删除空值和空值 - 清理嵌套对象
【发布时间】:2018-09-17 12:33:15
【问题描述】:

我得到了一个看起来像这样的对象:

{
    "a": "string not empty",
    "b": {
        "c": "string not empty",       
    },
    "d": {
        "e": false,
        "f": 0,
        "g": true,
        "h": 10
    },
    "i": {
        "j": 0,
        "k": null
    },
    "l": {
        "m": null
    },
    "n": {
        "o": 1,
        "p": "string (not empty)",
        "q": {}
    },
    "r": [],
    "l": "2000-01-01T01:01:00.000Z",
}

感谢此处提供的代码:https://stackoverflow.com/a/38364486/3912805 我现在可以删除嵌套对象的所有 null 值。

我使用这个功能至今removeNull

removeNull = (obj) => {
  Object.keys(obj).forEach(key =>
    (obj[key] && typeof obj[key] === 'object') && removeNull(obj[key]) ||
    (obj[key] === undefined || obj[key] === null) && delete obj[key]
  );
  return obj;
};

但我想增强此功能,以允许我删除嵌套对象中可能存在的所有空数组或任何空集合。

最终结果应该是没有 k, l & m, q, r, l:

{
    "a": "string not empty",
    "b": {
        "c": "string not empty",       
    },
    "d": {
        "e": false,
        "f": 0,
        "g": true,
        "h": 10
    },
    "i": {
        "j": 0
    },
    "n": {
        "o": 1,
        "p": "string (not empty)"
    },
    "l": "2000-01-01T01:01:00.000Z",
}

我需要保留所有设置为 0false 的值。

我想用 ES6 的方法来增强这个removeNull 的方法,但是到目前为止我没能做到。

我还尝试了用于此 How to deeply remove null values, empty objects and empty array from an object 的老式方法

itemToBool = item => {
  if (typeof item !== 'object' || item === null) return item;
  const cleanedItem = cleanObject(item);
  return Object.keys(cleanedItem).length !== 0 && cleanedItem;
};

cleanObject = obj => {
  if (Array.isArray(obj)) {
    const newArr = obj.map(itemToBool).filter(Boolean);
    return newArr.length && newArr;
  }
  const newObj = Object.entries(obj).reduce((a, [key, val]) => {
    const newVal = itemToBool(val);
    if (newVal !== null || newVal === false) a[key] = newVal;
    return a;
  }, {});
  return Object.keys(newObj).length > 0 && newObj;
};

但它也失败了。

【问题讨论】:

    标签: javascript ecmascript-6


    【解决方案1】:

    您可以通过迭代对象的键/值对并首先迭代嵌套的可迭代对象然后删除不需要的键来采取直接的方法。

    function clean(object) {
        Object
            .entries(object)
            .forEach(([k, v]) => {
                if (v && typeof v === 'object') {
                    clean(v);
                }
                if (v && typeof v === 'object' && !Object.keys(v).length || v === null || v === undefined) {
                    if (Array.isArray(object)) {
                        object.splice(k, 1);
                    } else {
                        delete object[k];
                    }
                }
            });
        return object;
    }
    
    var object = { a: "string not empty", b: { c: "string not empty" }, d: { e: false, f: 0, g: true, h: 10 }, i: { j: 0, k: null }, l: { m: null }, n: { o: 1, p: "string (not empty)", q: {} }, r: [{ foo: null }] };
    
    console.log(clean(object));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • delete object[k]; 应该是 Array.isArray(object) ? object.splice(k, 1) : delete object[k]; 例如"r": [] 曾是 "r": [{a:undefined}, {a:1}]
    • 我尝试调试了一下,但是如果我的嵌套对象中有r: "2018-01-01T00:00:00.000Z",它将使用您的方法将其删除
    • 你有Date 对象吗?如果是字符串,则保留。
    • 看来它毕竟是一个Date 对象。我怎样才能避免删除它们?
    • 我编辑了我的示例,到目前为止,我只是将它添加到您的解决方案中:if (Array.isArray(object)) object.splice(k, 1); else if (!(v instanceof Date)) delete object[k];
    【解决方案2】:

    您可以利用JSON.stringify,它是可选的第二个参数replacer,但请注意以下代码删除了null undefined

    const sanitize = (obj) => {
      return JSON.parse(JSON.stringify(obj, (key, value) => {
        return (value === null ? undefined : value);
      }));
    };
    
    const obj = {
      "a": "string not empty",
      "b": {
        "c": "string not empty",
      },
      "d": {
        "e": false,
        "f": 0,
        "g": true,
        "h": 10
      },
      "i": {
        "j": 0,
        "k": null
      },
      "l": {
        "m": null
      },
      "n": {
        "o": 1,
        "p": "string (not empty)",
        "q": {}
      },
      "r": [],
      "l": "2000-01-01T01:01:00.000Z",
    }
    
    console.log(sanitize(obj))

    【讨论】:

    • 这真的很有帮助而且更短。
    【解决方案3】:

    感谢 Nina Scholz,我的增强版将是:

    cleanObject = function(object) {
        Object
            .entries(object)
            .forEach(([k, v]) => {
                if (v && typeof v === 'object')
                    cleanObject(v);
                if (v && 
                    typeof v === 'object' && 
                    !Object.keys(v).length || 
                    v === null || 
                    v === undefined ||
                    v.length === 0
                ) {
                    if (Array.isArray(object))
                        object.splice(k, 1);
                    else if (!(v instanceof Date))
                        delete object[k];
                }
            });
        return object;
    }
    

    【讨论】:

    • 谢谢!可能&& !(v instanceof Date) 可以放在&& !Object.keys(v).length 之前,因为不需要在 if 块中输入日期检查 - 可以更早地检查日期
    【解决方案4】:

    如果你不想改变对象并且需要一个新的副本,那么你可以将对象字符串化为json并解析它,并在解析时进行过滤。如果您不需要源对象,则可以将结果覆盖到相同的引用中。它可能不是性能高效的方法,但显然更清洁,而不是自递归方法。

    var obj = {
        "a": "string not empty",
        "b": {
            "c": "string not empty",       
        },
        "d": {
            "e": false,
            "f": 0,
            "g": true,
            "h": 10
        },
        "i": {
            "j": 0,
            "k": null
        },
        "l": {
            "m": null
        },
        "n": {
            "o": 1,
            "p": "string (not empty)",
            "q": {}
        },
        "r": [],
        "s": {"t": null},
        "u": [null, {"v": {}}]
    }
    function copyNonEmpty(o) {
      let ignores = [null, undefined, ""],
        isNonEmpty = d => !ignores.includes(d) && (typeof(d) !== "object" || Object.keys(d).length)
      return JSON.parse(JSON.stringify(o), function(k, v) {
        if (isNonEmpty(v))
          return v;
      });
    }
    
    var res = copyNonEmpty(obj);
    console.log(JSON.stringify(res, null, 4));

    如果值为ObjectArray,则typeof 将返回objectObject.keys 将为这两种情况返回一个键数组("0", "1",2...数组),如果它是一个空数组或对象,则数组长度(键)将为0。因此,有条件地,它一定不能(nullundefined"")和(非 object/array OR object/array 这是非空的,然后你可以采取那个值。

    【讨论】:

      【解决方案5】:

      删除空数组、字符串、null、未定义值

      function removeEmptyElements(obj) {
        if (Array.isArray(obj)) {
          obj.forEach((element, index) => obj.splice(index, 1, removeEmptyElements(element)));
          return obj;
        }
        return Object.fromEntries(Object.entries(obj)
          .filter(([, v]) => (Array.isArray(v) ? v.length !== 0 : (v !== null && v !== '' && v !== undefined)))
          .map(([k, v]) => [k, v === (Object(v)) ? removeEmptyElements(v) : v]));
      }
      

      【讨论】:

        【解决方案6】:

        我试过了,如下

           const test = {
               a: '',
               b: 1,
               c: [],
               d: {
                e: null,
                f: 0,
                g: undefined,
                h: {
                    i: 'test',
                    j: {},
                    k: '',
                    l: {
                        m: 'yo test',
                        n: 'go for it'
                    }
                }
             },
            e: 'yo tested'
            };
        
            const JS_PRIMITIVE_TYPES = { 'string': 1, 'number': 1, 'undefined': 1, 'boolean': 1, 
            'symbol': 1 }
        
            const isValuePrimitiveType = (value) => {
            const typeOfVal = typeof value;
            if (JS_PRIMITIVE_TYPES.hasOwnProperty(typeOfVal)) {
                return true;
            }
            return false;
            }
        
            /* MAIN Function which runs and call other functions
               allKeys : keys of object Object.keys(test);
               badJson : json which needs to be update
            */
              const iterateObjForRemoveEmptyElem = (badJson, allKeys) => {
               for (let index = 0; index < allKeys.length; index++) {
                  const key = allKeys[index];
                  if (isEmpty(badJson[key])) {
                     delete badJson[key];
                  } else if (Array.isArray(badJson[key]) || isValuePrimitiveType(badJson[key])) {
                    continue;
                 }
                 else {
                    const newKeys = Object.keys(badJson[key]);
                    const newJson = Object.assign({}, badJson[key]);
                    badJson[key] = iterateObjForRemoveEmptyElem(newJson, newKeys);
                }
            }
            return badJson;
            }
        
        
        
            const isEmpty = (val) => {
             if(val === '' || val === null || val === undefined ) {
                 return true;
             } else if (Array.isArray(val) && val.length === 0){
                return true;
             } else if(typeof val === 'object' && Object.keys(val).length === 0){
                return true;
             }
            return false;
            }
        
            const myKeys = Object.keys(test);
            console.log("Final Result:::::",JSON.stringify(iterateObjForRemoveEmptyElem(test,myKeys)));

        这对我有效到第 n 级

        【讨论】:

          【解决方案7】:

          刚刚解决了同样的问题,所以想和大家分享一下。我的代码还清理了嵌套对象和数组,可以根据您的要求进行自定义:

          
          cleanObject = (input) => {
            if (typeof input === 'object' && input !== null) {
              if(Array.isArray(input)) {
                return input.map(cleanObject)
                            .filter(item => item !== null && item !== undefined) 
              }
          
              return Object.fromEntries(
                Object.entries(input)
                      .map(([key, val]) => [key, cleanObject(val)])
                      .filter(([k, v]) => v !== null && v !== undefined)
              );
          
            } 
          
            return input;
          }
          // testcase:
           const testVal = {
            a: 1,
            b: 2,
            c: undefined,
            d: { a: 99, b: null },
            e: { a: 1, b: 2, d: undefined, g: null, e: 0 },
            f: [1, 0, null, undefined],
            g: [1, 2],
            h: { aa: 1, bb: { c: 1, d: [111, null], e: 'hello' } },
          };
          
          cleanObject(testVal);
          
          

          【讨论】:

            【解决方案8】:
            //sample Json Response
            var items = {
                        name: 'test',
                        randomArray: [],
                         randomObject: {
                            id: null,
                            someObject: {},
                            someInternalArray: [],
                            someUndefinedObject: undefined,
                        },
                          New name: null,
                           nestedObject: [
                            {
                                  emp: {
                                    id: null,
                                },
                               empAssets: 2,
                               joiningDate: {
                                    startDate: null,
                                    endDate: '2019/12/01',
                                     Addresses: [],
                                },
                            },
                        ],
                    };
                   this.removeEmptyKeys(items);
                    console.log('the final items ‘,items);
            
            //Removing logic 
            removeEmptyKeys(yourObject) {
                    Object.keys(yourObject).forEach(key => {
                        if (
                            Object.prototype.toString.call(yourObject[key]) === '[object Date]' &&
                            (yourObject[key].toString().length === 0 ||
                                yourObject[key].toString() === 'Invalid Date')
                        ) {
                            delete yourObject[key];
                        } else if (yourObject[key] && typeof yourObject[key] === 'object') {
                            this.removeEmptyKeysFromObject(yourObject[key]);
                        } else if (yourObject[key] == null || yourObject[key] === '') {
                            delete yourObject[key];
                        }
            
                        if (
                            yourObject[key] &&
                            typeof yourObject[key] === 'object' &&
                            Object.keys(yourObject[key]).length === 0 &&
                            Object.prototype.toString.call(yourObject[key]) !== '[object Date]'
                        ) {
                            delete yourObject[key];
                        }
                    });
                    return yourObject;
                }
            

            删除未定义、空、空字符串、空数组。如果有帮助,请点赞。

            【讨论】:

              猜你喜欢
              • 2018-04-28
              • 2021-12-13
              • 1970-01-01
              • 2016-04-15
              • 2015-06-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多