需要一个操作对象并给出所需响应的通用功能

时间:2018-10-02 15:22:33

标签: javascript node.js lodash

我有以下JSON对象:

{
    "$and": [{
        "fname": "test"
    }, {
        "lname": "test1"
    }, {
        "$or": [{
            "age": 20
        }, {
            "address": "mumbai"
        }, {
            "$and": [{
                "fav": "java"
            }, {
                "price": 200
            }]
        }]
    }, {
        "java": "servlet"
    }, {
        "$and": [{
            "colour": "green"
        }, {
            "pin": 400
        }]
    }]
}

我想要一个JavaScript函数,将其转换为以下格式:

{
    "must": [{
        "fname": "test"
    }, {
        "lname": "test1"
    }, {
        "should": [{
            "age": 20
        }, {
            "address": "mumbai"
        }, {
            "must": [{
                "fav": "java"
            }, {
                "price": 200
            }]
        }]
    }, {
        "java": "servlet"
    }, {
        "must": [{
            "colour": "green"
        }, {
            "pin": 400
        }]
    }]
}

对于嵌套数组没有限制,因此需要一个通用函数,该函数遍历输入JSON对象并给出我想要的响应  请帮我做这个吗?

4 个答案:

答案 0 :(得分:1)

最优雅的方式:

 const output = JSON.parse(
   JSON.stringify(input)
    .replace(/"\$and"/g, `"must"`)
    .replace(/"\$or"/g, `"should"`)
 );

或者不太优雅:

 const replacer = ({ $and, $or, ...rest }) => ({ must: $and,  should: $or, ...rest });

 const mapDeep = (obj, mapper) => {
   const result = {};
   for(const [key, value] of Object.entries(mapper(obj))) {
     if(Array.isArray(value)) {
       result[key] = value.map(el => typeof el === "object" ? mapDeep(el, mapper) : el);
     } else if(typeof value === "object") {
       result[key] = mapDeep(value, mapper);
     } else {
       result[key] = value;
     }
   }
   return result;
 }

 const output = mapDeep(input, replacer);

答案 1 :(得分:1)

您将需要递归。这应该可以满足您的需求。

function findAndReplace(obj, find, replace){
  if(Array.isArray(obj)){
    obj.forEach((_obj) => findAndReplace(_obj, find, replace));  
  }else if(typeof(obj) === 'object'){
    for(var key in obj){
      findAndReplace(obj[key], find, replace);
      if(key === find){
        let temp = obj[key];
        obj[replace] = temp;
        delete obj[key];
      }      
    }
  }
}

let test = {
    "$and": [{
        "fname": "test"
    }, {
        "lname": "test1"
    }, {
        "$or": [{
            "age": 20
        }, {
            "address": "mumbai"
        }, {
            "$and": [{
                "fav": "java"
            }, {
                "price": 200
            }]
        }]
    }, {
        "java": "servlet"
    }, {
        "$and": [{
            "colour": "green"
        }, {
            "pin": 400
        }]
    }]
};
findAndReplace(test, "$and", "must");
findAndReplace(test, "$or", "should")
console.log(test);

答案 2 :(得分:0)

对于您而言,我认为最好的方法是这样的:

let str = JSON.stringify(t1);
str = str.replace(/[$]and/g, 'must');
str = str.replace(/[$]or/g, 'should');
const t2 = JSON.parse(str);

t1是您的json,而t2是转换后的json

答案 3 :(得分:0)

您可以递归使用lodash的_.transform()来替换密钥。该方法将迭代所有对象和数组,并用回调(cb)的结果替换所有键:

const mapKeysDeep = (obj, cb) =>
  _.transform(obj, (result, value, key) => {
    result[cb(key)] = _.isObject(value) ? mapKeysDeep(value, cb) : value;
  });

const obj = {"$and":[{"fname":"test"},{"lname":"test1"},{"$or":[{"age":20},{"address":"mumbai"},{"$and":[{"fav":"java"},{"price":200}]}]},{"java":"servlet"},{"$and":[{"colour":"green"},{"pin":400}]}]};

const replaceMap = new Map([['$and', 'must'], ['$or', 'should']]);

const result = mapKeysDeep(obj, key => replaceMap.get(key) || key);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>