JSONはネストできるので、末端の要素までアクセスするためにはちょっとした工夫をしなければならない。
ということで、再帰呼び出しをつかってJSONのすべての要素にアクセスする方法を考えてみた。
ネストされたJSONの要素にアクセスする
var json = {
    "a1": {
        "a1-b1": 1,
        "a1-b2": 2,
        "a1-b3": {
            "a1-b3-c1": 1
        }
    },
    "a2": {
        "a2-b1": 1,
        "a2-b2": 2
    },
    "a3": "3"
};
var walkJSON = function walkJSON(data, callback){
    for (var key in data) {
        callback(key, data[key]);
        if (typeof data[key] === "object") {
            walkJSON(data[key], callback);
        }
    }
}
walkJSON(json, function(key, value) {
    console.log(key + ":" + value); 
});
// 出力結果
//   a1:[object Object]
//   a1-b1:1
//   a1-b2:2
//   a1-b3:[object Object]
//   a1-b3-c1:1
//   a2:[object Object]
//   a2-b1:1
//   a2-b2:2
//   a3:3typeofを使うときはちょっとクセがあるので注意が必要!
▶ JavaScriptでオブジェクトの型を判別するのにtypeof演算子使うとツラいよね - Qiita
さらに再帰を使うときは、末尾再帰の最適化がされていない言語だとスタックオーバーフローが発生する。
▶ JavaScript - 末尾再帰による最適化 - Qiita
JSON.parseでもっと簡単に
JSON.parseの第二引数(reviver)を定義すると、もっと簡単にJSONのすべての要素にアクセスできる。
var json = {
    "a1": {
        "a1-b1": 1,
        "a1-b2": 2,
        "a1-b3": {
            "a1-b3-c1": 1
        }
    },
    "a2": {
        "a2-b1": 1,
        "a2-b2": 2
    },
    "a3": "3"
};
JSON.parse(JSON.stringify(json), function(key, value){
    console.log(key + ":" + value);
    return value;
});
// 出力結果
//    a1-b1:1
//    a1-b2:2
//    a1-b3-c1:1
//    a1-b3:[object Object]
//    a1:[object Object]
//    a2-b1:1
//    a2-b2:2
//    a2:[object Object]
//    a3:3
//    :[object Object]簡単にできるけど、アクセスする順番が最下層からになってしまう。
もし定義されたJSONを上からアクセスしたいという場合は、前述の再帰呼び出しによる処理が必要となる。
参考サイト
- JSON - JavaScript | MDN
- JSON.parse() - JavaScript | MDN
- JavaScriptでオブジェクトの型を判別するのにtypeof演算子使うとツラいよね – Qiita
- JavaScript - 末尾再帰による最適化 – Qiita
ちなみに再帰呼び出しについては、書いてある量は少ないが「JavaScript: The Good Parts」がオススメ。
以上
written by @bc_rikko
 


 
0 件のコメント :
コメントを投稿