Tôi đã ném một số mã với nhau để làm phẳng và hủy làm phẳng các đối tượng JSON phức tạp / lồng nhau. Nó hoạt động, nhưng hơi chậm (kích hoạt cảnh báo 'tập lệnh dài').
Đối với các tên phẳng tôi muốn "." làm dấu phân cách và [INDEX] cho mảng.
Ví dụ:
un-flattened | flattened
---------------------------
{foo:{bar:false}} => {"foo.bar":false}
{a:[{b:["c","d"]}]} => {"a[0].b[0]":"c","a[0].b[1]":"d"}
[1,[2,[3,4],5],6] => {"[0]":1,"[1].[0]":2,"[1].[1].[0]":3,"[1].[1].[1]":4,"[1].[2]":5,"[2]":6}
Tôi đã tạo một điểm chuẩn ~ mô phỏng trường hợp sử dụng của mình http://jsfiddle.net/WSzec/
- Nhận một đối tượng JSON lồng nhau
- Làm phẳng nó
- Nhìn qua nó và có thể sửa đổi nó trong khi làm phẳng
- Hủy kết nối nó trở lại định dạng lồng nhau ban đầu của nó sẽ được chuyển đi
Tôi muốn mã nhanh hơn: Để làm rõ, mã hoàn thành điểm chuẩn JSFiddle ( http://jsfiddle.net/WSzec/ ) nhanh hơn đáng kể (~ 20% + sẽ tốt hơn) trong IE 9+, FF 24+ và Chrome 29 +.
Đây là mã JavaScript có liên quan: Nhanh nhất hiện tại: http://jsfiddle.net/WSzec/6/
JSON.unflatten = function(data) {
"use strict";
if (Object(data) !== data || Array.isArray(data))
return data;
var result = {}, cur, prop, idx, last, temp;
for(var p in data) {
cur = result, prop = "", last = 0;
do {
idx = p.indexOf(".", last);
temp = p.substring(last, idx !== -1 ? idx : undefined);
cur = cur[prop] || (cur[prop] = (!isNaN(parseInt(temp)) ? [] : {}));
prop = temp;
last = idx + 1;
} while(idx >= 0);
cur[prop] = data[p];
}
return result[""];
}
JSON.flatten = function(data) {
var result = {};
function recurse (cur, prop) {
if (Object(cur) !== cur) {
result[prop] = cur;
} else if (Array.isArray(cur)) {
for(var i=0, l=cur.length; i<l; i++)
recurse(cur[i], prop ? prop+"."+i : ""+i);
if (l == 0)
result[prop] = [];
} else {
var isEmpty = true;
for (var p in cur) {
isEmpty = false;
recurse(cur[p], prop ? prop+"."+p : p);
}
if (isEmpty)
result[prop] = {};
}
}
recurse(data, "");
return result;
}
EDIT 1 Sửa đổi cách thực hiện ở trên thành triển khai của @Bergi hiện đang nhanh nhất. Bên cạnh đó, sử dụng ".indexOf" thay vì "regex.exec" nhanh hơn khoảng 20% trong FF nhưng chậm hơn 20% trong Chrome; vì vậy tôi sẽ gắn bó với regex vì nó đơn giản hơn (đây là nỗ lực của tôi trong việc sử dụng indexOf để thay thế regex http://jsfiddle.net/WSzec/2/ ).
EDIT 2 Dựa trên ý tưởng của @Bergi, tôi đã tạo ra một phiên bản phi regex nhanh hơn (nhanh hơn gấp 3 lần trong FF và nhanh hơn 10% trong Chrome). http://jsfiddle.net/WSzec/6/ Trong triển khai (hiện tại) này, các quy tắc cho tên khóa chỉ đơn giản, các khóa không thể bắt đầu bằng một số nguyên hoặc chứa một dấu chấm.
Thí dụ:
- {"foo": {"thanh": [0]}} => {"foo.bar.0": 0}
EDIT 3 Thêm cách tiếp cận phân tích cú pháp đường dẫn nội tuyến của @AaditMShah (chứ không phải String.split) đã giúp cải thiện hiệu suất không kết hợp. Tôi rất hài lòng với sự cải thiện hiệu suất tổng thể đạt được.
Jsfiddle và jsperf mới nhất:
[1].[1].[0]
có vẻ sai với tôi Bạn có chắc chắn đây là kết quả mong muốn?