如何 select 更正多级对象的值?

How to select correct values from multiple level object?

我有一个对象:

const options = {
option1: 'big',
option2: undefined,
option3: [],
option4: ['heavy'],
optionList: {
  option5: undefined,
  option6: true,
  option7: ['blue', 'pink', 'green']
  }
}

我想基于它构建 URL。如果选项是 undefined 或具有空数组,则需要跳过该选项。如果选项是对象,它里面的选项应该经过同样的检查。基于我想要得到的对象 URL:

?option1=big&option4=heavy&option6=true&option7=blue&option7=pink&option7=green

正在考虑可能使用 new URLSearchParams,但不确定如何有效地转换上述对象。

这是一个值得尝试解决的有趣问题。我想我有一个适合你的解决方案。

function nestedObj(obj) {
  let optionStrings = [];

  function recursiveHelper(obj) {
    for (const [key, value] of Object.entries(
      obj
    )) {
      if (
        typeof value === 'object' &&
        !value.length
      ) {
        recursiveHelper(value);
      } else if (
        value !== undefined &&
        typeof value === 'object' &&
        value.length > 0
      ) {
        for (let i = 0; i < value.length; i++) {
          optionStrings.push(
            `${key}=${value[i]}`
          );
        }
      } else if (value !== undefined) {
        optionStrings.push(`${key}=${value}`);
      }
    }
  }

  recursiveHelper(obj);
  return optionStrings;
}

const options = {
  option1: 'big',
  option2: undefined,
  option3: [],
  option4: ['heavy'],
  optionList: {
    option5: undefined,
    option6: true,
    option7: ['blue', 'pink', 'green'],
  },
};

let queryStringArray = nestedObj(options);

let queryString = `?${queryStringArray.join(
  '&'
)}`;

console.log(queryString);

您的约束使 if/else if 逻辑变得有趣。 recursiveHelper 函数中的 if 语句检查值的类型是否为对象,如果是,则通过查看值 属性 是否已定义来检查它是否为数组,因为数组具有 属性. else if 语句检查当前值是否未定义,并通过再次确认它是一个定义了长度 属性 且长度大于 0 的对象类型来检查该值是否不是空数组这样我们就可以在有多个选项的情况下遍历数组,就像 option7 属性 的情况一样。最后一个 else if 语句是任何其他值,例如字符串、布尔值或数字,并创建必要的字符串以推送 optionStrings 数组。 optionStrings 数组在递归函数执行完成后返回,这样我们就可以使用数组上可用的 join 方法连接不同的 optionStrings 以形成最终的查询字符串。希望这能解决您的问题!

此转换有 2 个主要问题;

  1. 过滤嵌套对象(取决于值(不是未定义的))
  2. 崩溃到数组项(对于所需的 url 查询)
function recursiveObjectFilter(obj = {}){
    let result = {};

    for(let key in obj){
        let currentItem = obj[key];

        //INFO: checks value exist?
        if(currentItem !== undefined){
            //WARNING: arrays return 'object' so we have to check is this value array or object
            if(typeof currentItem == 'object'){
                if(Array.isArray(currentItem)){
                    if(currentItem.length){
                        result[key] = currentItem;
                    }
                }else{
                    //INFO: call 'recursiveObjectFilter' for child objects and merge result
                    let subResult = recursiveObjectFilter(currentItem);
                    result = {
                        ...result,
                        ...subResult
                    }
                }
            }else{
                result[key] = currentItem;
            }
        }
    }

    return result;
}

function generateKeyValueArray(obj = {}){
    let result = [];

    for(let key in obj){
        let currentValue = obj[key];

        if(Array.isArray(currentValue)){
            for(let i in currentValue){
                let currentArrayValue = currentValue[i];

                let currentPair = [key, currentArrayValue];
                result.push(currentPair);
            }
        }else{
            let currentPair = [key, currentValue];
            result.push(currentPair);
        }
    }

    return result;
}

function generateUrlSearchParams(valueObj = {}){
    let filteredValueObj = recursiveObjectFilter(valueObj);
    //INFO: URLSearchParams accepts Objects but array values must be pass as seperated key/value pairs for desired result (`option7=blue&option7=pink&option7=green`), so we use translation.  
    let urlSearchParamsDataSource = generateKeyValueArray(filteredValueObj);
    
    let urlSearchParams = new URLSearchParams(urlSearchParamsDataSource);

    return urlSearchParams;
}

const options = {
    option1: 'big',
    option2: undefined,
    option3: [],
    option4: ['heavy'],
    optionList: {
        option5: undefined,
        option6: true,
        option7: ['blue', 'pink', 'green']
    }
}

let myUrlSearchParams = generateUrlSearchParams(options);
console.log(myUrlSearchParams.toString());
//Prints 'option1=big&option4=heavy&option6=true&option7=blue&option7=pink&option7=green'

recursiveObjectFilter 函数过滤值(但如果存在与父项具有相同键的项,则其覆盖值)

generateKeyValueArray 函数生成 key/value 对数组,在本例中为 returns [["option1","big"],["option4","heavy"],["option6",true],["option7","blue"],["option7","pink"],["option7","green"]]

抽象函数对于整洁的代码和可重用性很有用。