由于JSON无法执行函数,因此我需要通过JSON对象中的键标志来评估JSON字符串。我想以对象形式改变JSON数据。
我无法在线找到一个功能/方法,可以根据已知的密钥模式为我提供密钥的完整路径。
鉴于此数据:
{
"js:bindto": "#chart-1", // note the key here 'js:'
"point": {
"r": 5
},
"data": {
"x": "x",
"xFormat": "%Y",
"columns": [
...
],
"colors": {
"company": "#ed1b34",
"trendline": "#ffffff"
}
},
"legend": {
"show": false
},
"axis": {
"x": {
"padding": {
"left": 0
},
"type": "timeseries",
"tick": {
"format": "%Y",
"outer": false
}
},
"y": {
"tick": {
"outer": false,
"js:format": "d3.format(\"$\")" // note the key here 'js:'
}
}
},
"grid": {
"lines": {
"front": false
},
"y": {
"lines": [...]
}
}
}
标志是以js:
开头的键。
如果我查找js:format
,我希望它的路径类似于:/js:bindto
和/axis/y/tick/js:format
。接受建议。
在上下文中:
mutateGraphData<T>(data:T):T {
// data here is a parsed JSON string. ( an object as shown above )
let jsonKeys = this.findKeysInJSON(JSON.stringify(data), "js:");
// jsonKeys = ["js:bindto","js:format"]
jsonKeys.map((key:string) => {
// find the key in data, then modify the value. (stuck here)
// i need the full path to the key so i can change the data property that has the key in question
});
});
return data;
}
findKeysInJSON<T>(jsonString:string, key:string):Array<T> {
let keys = [];
if (Boolean(~(jsonString.indexOf(`"${key}`)))) {
let regEx = new RegExp(key + "(\\w|\\-)+", "g");
keys = jsonString.match(regEx);
}
return keys;
}
我已经参加了几个npm套餐:
我看了
我看到的任何内容都无法返回相关密钥的完整路径,因此我可以对其进行修改,也不会直接在对象本身上工作,因此我可以更改其属性。
答案 0 :(得分:1)
你可以选择Ramda。它内置了函数,允许您以完全不可变的方式映射对象并修改对象的各个部分。
Ramda提供R.lensPath
,允许您深入挖掘对象,并根据需要进行修改。它不遵循您想要的模式,但我们可以使用lensify
函数快速修补它。
正在使用R.set
函数将节点设置为传入的值,并创建一个将在传入的对象上运行所有操作的管道。
你可以用ramda和镜头做一些非常酷的东西。在livecoding.tv上查看evilsoft以获得非常好的概述。
const obj={"js:bindto":"#chart-1",point:{r:5},data:{x:"x",xFormat:"%Y",columns:[],colors:{company:"#ed1b34",trendline:"#ffffff"}},legend:{show:!1},axis:{x:{padding:{left:0},type:"timeseries",tick:{format:"%Y",outer:!1}},y:{tick:{outer:!1,"js:format":'d3.format("$")'}}},grid:{lines:{front:!1},y:{lines:[]}}}
const lensify = path => R.lensPath(path.split('/'))
// create the property accessors split by /
const bindToLens = lensify('js:bindto')
const formatLens = lensify('axis/y/tick/js:format')
const modifyObj = R.pipe(
R.set(bindToLens, 'dis be bind'),
R.set(formatLens, 'I been here')
)
console.log(modifyObj(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
答案 1 :(得分:0)
在浏览一下后,我修改了Javascript/JSON get path to given subnode? @ adam-rackis
的答案function search(obj, target, path = "") {
for (var k in obj) {
if (obj.hasOwnProperty(k))
if (k === target)
return path + "." + k;
else if (typeof obj[k] === "object") {
var result = search( obj[k], target, path + "." + k );
if (result){
return result;
}
}
}
return false;
}
search(data,"js:format").slice(1); // returns: axis.y.tick.js:format
search(data,"js:bindto").slice(1); // returns: js:bindto
现在,我可以使用dotty
或object-resolve-path
或简单split('.')
来解析对象的路径。
答案 2 :(得分:0)
对于object-scan,这应该是一个衬里。我们已经在数据处理中大量使用了它,一旦您将其放在头上,它就会很强大。这是您可以使用它的方式
const objectScan = require('object-scan');
const find = (data) => objectScan(['**.js:*'], { joined: true })(data);
const data = {"js:bindto":"#chart-1","point":{"r":5},"data":{"x":"x","xFormat":"%Y","columns":[],"colors":{"company":"#ed1b34","trendline":"#ffffff"}},"legend":{"show":false},"axis":{"x":{"padding":{"left":0},"type":"timeseries","tick":{"format":"%Y","outer":false}},"y":{"tick":{"outer":false,"js:format":"d3.format(\"$\")"}}},"grid":{"lines":{"front":false},"y":{"lines":[]}}};
console.log(find(data));
// => [ 'axis.y.tick.js:format', 'js:bindto' ]