2015/11/14

【JavaScript】ネストされたJSONのすべての要素にアクセスする

JSONを読み込んで、編集して、出力するというツールをつくっていた。
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:3

typeofを使うときはちょっとクセがあるので注意が必要!
▶ 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を上からアクセスしたいという場合は、前述の再帰呼び出しによる処理が必要となる。



参考サイト





ちなみに再帰呼び出しについては、書いてある量は少ないが「JavaScript: The Good Parts」がオススメ。


以上

written by @bc_rikko

0 件のコメント :

コメントを投稿