在多维 javascript 对象中递归查找和替换
recursive find and replace in multidimensional javascript object
我需要在我的对象中查找并替换与正则表达式匹配的值(例如 **myVar**);我需要循环的对象是用户定义的,结构各不相同。
这是一个示例对象,为简单起见缩短了。
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: []
}
此对象被传递到主函数中,该函数使用传入的对象构建 angularjs 资源对象。
这是我使用的结构:
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()是基于下面的questions/answers,但我的情况不同,因为传入的对象(var testObject)的结构和找到的匹配的位置会发生变化。
- 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
所以...
这是我的递归解决方案,用于查找与所需正则表达式匹配的值
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;
}
此函数成功找到与正则表达式匹配的值,但是,如果不直接引用 testObject 的结构,我似乎无法 return 更新的对象。
这是上面代码的 jsfiddle。 http://jsfiddle.net/joshvito/2Lu4oexj/
我的目标是能够搜索传入的对象,找到与正则表达式匹配的任何值,并将该值更改为 userVars 中定义的值(如果对象值和 userVar 键匹配)。
我已经根据你的问题做了一个解决方案,一个复杂对象中的搜索和替换...'会帮助你吗?
不更改对象引用,仅替换字符串...
可以看到这个例子 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;
您可以通过在内部调用此函数来实现您的解决方案
如何 JSON.stringify 并替换为字符串并返回 JSON?
JSON.parse(JSON.stringify(testObject).replace(/\*\*([^*]+)\*\*/g,function([=10=],){return uvars[]||[=10=];}))
我根据需要修改了 Luan Castros 解决方案。请注意,for(key in myObject)
不被 linters 使用,因为它还遍历原型属性,这可能是不需要的。同时,Object.keys(myObject)
也适用于数组。
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);
}
- 第一:解决key递归重命名问题。您可以使用 map keys deep
- 然后:写下你的 iteratee 以便你 return 新键名
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;
});
对于基本数据处理,我们现在使用 object-scan。它非常强大,让事情变得更干净,但你需要花点时间来理解它。这是您解决问题的方法
请注意,该函数会改变对象和 returns 替换次数。如果你只想替换第一次出现的地方,你可以将 abort
设置为 true
// const objectScan = require('object-scan');
const replace = (p, n, data) => objectScan(['**'], {
rtn: 'count',
filterFn: ({ value, parent, property }) => {
if (p.test(value)) {
parent[property] = n;
return true;
}
return false;
}
})(data);
const 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: [] };
const r = replace(new RegExp('\*\*\w*\*\*', 'g'), 'newValue', testObject);
console.log(r);
// => 1
console.log(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: 'newValue' } ], queryParam: [], request_payload: "{'title':'EnterAname'}", returnList: [] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>
免责声明:我是object-scan
的作者
我需要在我的对象中查找并替换与正则表达式匹配的值(例如 **myVar**);我需要循环的对象是用户定义的,结构各不相同。
这是一个示例对象,为简单起见缩短了。
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: []
}
此对象被传递到主函数中,该函数使用传入的对象构建 angularjs 资源对象。
这是我使用的结构:
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()是基于下面的questions/answers,但我的情况不同,因为传入的对象(var testObject)的结构和找到的匹配的位置会发生变化。
- 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
所以... 这是我的递归解决方案,用于查找与所需正则表达式匹配的值
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;
}
此函数成功找到与正则表达式匹配的值,但是,如果不直接引用 testObject 的结构,我似乎无法 return 更新的对象。
这是上面代码的 jsfiddle。 http://jsfiddle.net/joshvito/2Lu4oexj/
我的目标是能够搜索传入的对象,找到与正则表达式匹配的任何值,并将该值更改为 userVars 中定义的值(如果对象值和 userVar 键匹配)。
我已经根据你的问题做了一个解决方案,一个复杂对象中的搜索和替换...'会帮助你吗?
不更改对象引用,仅替换字符串...
可以看到这个例子 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;
您可以通过在内部调用此函数来实现您的解决方案
如何 JSON.stringify 并替换为字符串并返回 JSON?
JSON.parse(JSON.stringify(testObject).replace(/\*\*([^*]+)\*\*/g,function([=10=],){return uvars[]||[=10=];}))
我根据需要修改了 Luan Castros 解决方案。请注意,for(key in myObject)
不被 linters 使用,因为它还遍历原型属性,这可能是不需要的。同时,Object.keys(myObject)
也适用于数组。
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);
}
- 第一:解决key递归重命名问题。您可以使用 map keys deep
- 然后:写下你的 iteratee 以便你 return 新键名
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;
});
对于基本数据处理,我们现在使用 object-scan。它非常强大,让事情变得更干净,但你需要花点时间来理解它。这是您解决问题的方法
请注意,该函数会改变对象和 returns 替换次数。如果你只想替换第一次出现的地方,你可以将 abort
设置为 true
// const objectScan = require('object-scan');
const replace = (p, n, data) => objectScan(['**'], {
rtn: 'count',
filterFn: ({ value, parent, property }) => {
if (p.test(value)) {
parent[property] = n;
return true;
}
return false;
}
})(data);
const 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: [] };
const r = replace(new RegExp('\*\*\w*\*\*', 'g'), 'newValue', testObject);
console.log(r);
// => 1
console.log(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: 'newValue' } ], queryParam: [], request_payload: "{'title':'EnterAname'}", returnList: [] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>
免责声明:我是object-scan
的作者