[英]Convert javascript dot notation object to nested object
我正在嘗試構建一個 function 來擴展 object,例如:
{
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2'
}
進入嵌套 object:
{ab: {cd: {e:'foo', f:'bar'}, g:'foo2'}}
像這樣 php function: Set::expand()
當然不使用 eval 。
我相信這就是你所追求的:
function deepen(obj) { const result = {}; // For each object path (property key) in the object for (const objectPath in obj) { // Split path into component parts const parts = objectPath.split('.'); // Create sub-objects along path as needed let target = result; while (parts.length > 1) { const part = parts.shift(); target = target[part] = target[part] || {}; } // Set value at end of path target[parts[0]] = obj[objectPath] } return result; } // For example ... console.log(deepen({ 'ab.cd.e': 'foo', 'ab.cd.f': 'bar', 'ab.g': 'foo2' }));
如果您使用的是 Node.js(例如 - 如果沒有從我們的模塊中剪切和粘貼),請嘗試這個包: https : //www.npmjs.org/package/dataobject-parser
構建了一個執行正向/反向操作的模塊:
https://github.com/Gigzolo/dataobject-parser
它現在被設計為一個自我管理的對象。 通過實例化 DataObjectParser 的實例使用。
var structured = DataObjectParser.transpose({
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2'
});
structured.data()
返回您的嵌套對象:
{ab: {cd: {e:'foo', f:'bar'}, g:'foo2'}}
所以這是 JSFiddle 中的一個工作示例:
函數名稱很糟糕,代碼很快就完成了,但它應該可以工作。 請注意,這會修改原始對象,我不確定您是否要創建一個舊對象的擴展版本的新對象。
(function(){
function parseDotNotation( str, val, obj ){
var currentObj = obj,
keys = str.split("."), i, l = keys.length - 1, key;
for( i = 0; i < l; ++i ) {
key = keys[i];
currentObj[key] = currentObj[key] || {};
currentObj = currentObj[key];
}
currentObj[keys[i]] = val;
delete obj[str];
}
Object.expand = function( obj ) {
for( var key in obj ) {
parseDotNotation( key, obj[key], obj );
}
return obj;
};
})();
var expanded = Object.expand({
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2'
});
JSON.stringify( expanded );
//"{"ab":{"cd":{"e":"foo","f":"bar"},"g":"foo2"}}"
源自Esailja 的答案,修復了支持多個頂級鍵的問題。
(function () {
function parseDotNotation(str, val, obj) {
var currentObj = obj,
keys = str.split("."),
i, l = Math.max(1, keys.length - 1),
key;
for (i = 0; i < l; ++i) {
key = keys[i];
currentObj[key] = currentObj[key] || {};
currentObj = currentObj[key];
}
currentObj[keys[i]] = val;
delete obj[str];
}
Object.expand = function (obj) {
for (var key in obj) {
if (key.indexOf(".") !== -1)
{
parseDotNotation(key, obj[key], obj);
}
}
return obj;
};
})();
var obj = {
"pizza": "that",
"this.other": "that",
"alphabets": [1, 2, 3, 4],
"this.thing.that": "this"
}
輸出:
{
"pizza": "that",
"alphabets": [
1,
2,
3,
4
],
"this": {
"other": "that",
"thing": {
"that": "this"
}
}
}
您可以將鍵字符串拆分為路徑,並通過使用未訪問級別的默認對象來減少它以分配值。
function setValue(object, path, value) { var keys = path.split('.'), last = keys.pop(); keys.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value; return object; } var source = { 'ab.cd.e': 'foo', 'ab.cd.f': 'bar', 'ab.g': 'foo2' }, target = Object .entries(source) .reduce((o, [k, v]) => setValue(o, k, v), {}); console.log(target);
這是@broofa 提供的答案,但已轉換為 TypeScript。
type NestedObject = { [key: string]: any };
function objectify(obj: NestedObject): NestedObject {
const result: NestedObject = {};
for (const key in obj) {
let target: NestedObject = result;
const parts = key.split(".");
for (let j = 0; j < parts.length - 1; j++) {
const part = parts[j];
target = target[part] = target[part] || {};
}
target[parts[parts.length - 1]] = obj[key];
}
return result;
}
這是我在我的一個應用程序中執行此操作的方法:
const obj = { "start.headline": "1 headline", "start.subHeadline": "subHeadline", "start.accordion.headline": "2 headline", "start.accordion.sections.0.content": "content 0", "start.accordion.sections.0.iconName": "icon 0", "start.accordion.sections.1.headline": "headline 1", "start.accordion.sections.1.content": "content 1", "start.accordion.sections.1.iconName": "icon 1", "start.accordion.sections.2.headline": "headline 2", "start.accordion.sections.2.content": "content 2", "start.accordion.sections.2.iconName": "icon 2", "end.field": "add headline", "end.button": "add button", "end.msgs.success": "success msg", "end.msgs.error": "error msg", }; const res = Object.keys(obj).reduce((res, key) => { const path = key.split('.'); const lastIndex = path.length - 1; path.reduce( (acc, k, i, a) => acc[k] = lastIndex === i? obj[key]: acc[k] || (/\d/.test(a[i+1])? []: {}), res ); return res; }, {}); console.log(res);
您需要將每個字符串鍵轉換為對象。 使用以下功能,您可以獲得所需的結果。
function convertIntoJSON(obj) {
var o = {}, j, d;
for (var m in obj) {
d = m.split(".");
var startOfObj = o;
for (j = 0; j < d.length ; j += 1) {
if (j == d.length - 1) {
startOfObj[d[j]] = obj[m];
}
else {
startOfObj[d[j]] = startOfObj[d[j]] || {};
startOfObj = startOfObj[d[j]];
}
}
}
return o;
}
現在調用這個函數
var aa = {
'ab.cd.e': 'foo',
'ab.cd.f': 'bar',
'ab.g': 'foo2'
};
var desiredObj = convertIntoJSON(aa);
可行的方法,但可能不是最有效的方法(也依賴於 ECMA 5 Object.keys() 方法,但可以輕松替換。
var input = {
'ab.cd.e': 'foo',
'ab.cd.f': 'bar',
'ab.g': 'foo2'
};
function createObjects(parent, chainArray, value) {
if (chainArray.length == 1) {
parent[chainArray[0]] = value;
return parent;
}
else {
parent[chainArray[0]] = parent[chainArray[0]] || {};
return createObjects(parent[chainArray[0]], chainArray.slice(1, chainArray.length), value);
}
}
var keys = Object.keys(input);
var result = {};
for(var i = 0, l = keys.length; i < l; i++)
{
createObjects(result, keys[i].split('.'), input[keys[i]]);
}
JSFiddle 在這里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.