recursive find and replace in multidimensional javascript object

半腔热情 提交于 2020-08-24 03:53:04

问题


I need to find and replace values in my object when they match a regular expression (e.g. **myVar**); The object that I need to loop through is user defined and structure varies.

Here is an example object, shortened for simplicity.

var testObject = {
    name: "/pricing-setups/{folderId}", 
    method: "POST", 
    endpoint: "/pricing-setups/:folderId", 
    functionName: "create",
    Consumes: null,
    filename: "apicontracts/pricingsetups/PricingSetupServiceProxy.java",
    pathParam: [
        {$$hashKey: "06S",
          key: "folderId",
          value: "**myVar**"}
    ],
    queryParam: [],
    request_payload: "{'title':'EnterAname'}",
    returnList: []
}

This object is passed into a master function that builds a angularjs resource object using the passed in object.

Here is the structure I am using:

function getTestResult(dataSource, options) {
      //input into the service should be api obj and selected environment obj

      //extend the passed object with options if passed
      var opts = $.extend({}, dataSource, options);
      //swap the {param} syntax for :param in opts.endpoint
      opts.endpoint = opts.endpoint.replace(/\}/g, "").replace(/\{/g, ":");

      //replace any defined vars passed in from scenario via scenario.userVar
      opts = replaceUserVars(opts, {"myVar": "C=1000=Corporate"});

    //MORE CODE STUFF
    // ...
    // ...
}

replaceUserVars() is based on the following questions/answers, but my case is different because the structure of the passed in object (var testObject) and the location of the found match will change.

  • JSON Object array inside array find and replace in javascript
  • How to iterate through all keys & values of nested object?
  • Traverse all the Nodes of a JSON Object Tree with JavaScript

SO... Here is my recursive solution to find the values that match the desired regex

function replaceUserVars(api, uvars) {
      if (!uvars) {
        return api;
      }
      var pattern =  new RegExp("\\*\\*\\w*\\*\\*", "g");//match **myVar**
      //check the api params for a match to regex
      // and if we find a match, replace the string with the userVar[regex match].value

      function warpSpeedAhead(collection) {
        _.find(collection, function (obj) { //find obj in api
          if (obj !== null && typeof(obj) === "object") {
            warpSpeedAhead(obj);
          }
          else {
            if (pattern.test(obj)) { //check the regex
              var sanitVar = obj.replace(/\*/g, ""); //remove the *
              if (uvars[sanitVar]) {
                console.log("found one");
                obj = uvars[sanitVar];
                //should be equivalent to 
                //api.pathParam[0][key] = uvars[sanitVar]; //works in this case ONLY
              }
            }
          }
        });
      }
      warpSpeedAhead(api);

      return api;
    }

This function successfully finds the values that match the regex, however, I can't seem to return the updated object without directly refrencing the structure of the testObject.

Here is a jsfiddle of the code above. http://jsfiddle.net/joshvito/2Lu4oexj/

My goal is to be able to search through the incoming object, find any values that match the regular expression, and change the value to the value defined in userVars (if the object value and userVar key match).


回答1:


I've made a solution based in your problem, a search and replacer in a complex object... 'll help you?

not change the object reference, only replace in strings...

can see a example in this fiddle... http://jsfiddle.net/Castrolol/gvpnxou0/

/* definition */

function replaceVars(objSource, objReplacer){

    var pattern = replaceVars.pattern;

    if(typeof objSource === "object" ){     
        if(objSource === null) return null;

        if(objSource instanceof Array){
            for(var i = 0; i < objSource.length; i++){
             objSource[i] =  replaceVars(objSource[i], objReplacer); 
            }           
        }else{        
            for(var property in objSource){         
                objSource[property] = replaceVars(objSource[property], objReplacer);            
            }
        }

        return objSource;

    }

    if(typeof objSource === "string"){

        return objSource.replace(pattern, function(finded, varName){
            return varName in objReplacer ? objReplacer[varName] : finded;
        });

    }

    return objSource;

}


 replaceVars.pattern = /\*\*([0-9a-z_$]{1,})\*\*/gi;

you can implement your solution with calling internally this function




回答2:


How about JSON.stringify and replace as string and back to JSON?

JSON.parse(JSON.stringify(testObject).replace(/\*\*([^*]+)\*\*/g,function($0,$1){return uvars[$1]||$0;}))



回答3:


I modified Luan Castros solution to my needs. Note that for(key in myObject) is discouraged by linters, because of it also traverses the prototype attributes, which may be unwanted. At the same time, the Object.keys(myObject) will nicely work also on arrays.

function recursiveSubStringReplace (source, pattern, replacement) {

    function recursiveReplace (objSource) {
        if (typeof objSource === 'string') {
            return objSource.replace(pattern, replacement);
        }

        if (typeof objSource === 'object') {
            if (objSource === null) {
                return null;
            }

            Object.keys(objSource).forEach(function (property) {
                objSource[property] = recursiveReplace(objSource[property]);
            });

            return objSource;
        }

    }

    return recursiveReplace(source);
}



回答4:


  • First: solve the problem of recursively renaming a key. You can use map keys deep
  • Then: write your iteratee so that you return the new key name

const yourObject = { 'a': 1, 'b': 2 }; _.mapKeys(yourObject, function(value, key) { const pattern = /.*/; // whatever you want to match if (key.match(pattern)){ return key + "1234"; // return the new key name } return key; });



来源:https://stackoverflow.com/questions/29473526/recursive-find-and-replace-in-multidimensional-javascript-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!