ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

(たぶん)ドキュメントに書いてないExt.data.JsonReaderのrootの書き方。

概要

JSONデータの2階層目以降に欲しいデータがある場合のrootの書き方。

{
    response: {
        results: 2000, // Reader's configured totalProperty
        rows: [        // Reader's configured root
            // record data objects:
            { id: 1, firstname: 'Bill', occupation: 'Gardener' },
            { id: 2, firstname: 'Ben' , occupation: 'Horticulturalist' },
            ...
        ]
    }
}

というJSONデータがあった場合、rowsの部分をデータとして使いたい場合。

前提

Sencha Touch0.93の話です。

ドキュメントに書いてある例

JSONデータ
{
    results: 2000, // Reader's configured totalProperty
    rows: [        // Reader's configured root
        // record data objects:
        { id: 1, firstname: 'Bill', occupation: 'Gardener' },
        { id: 2, firstname: 'Ben' , occupation: 'Horticulturalist' },
        ...
    ]
}
読み込むコード
var myReader = new Ext.data.Store({
    proxy: {
        type: 'ajax',
        reader: {
            type: 'json',
            // metadata configuration options:
            idProperty: 'id'
            root: 'rows',
            totalProperty: 'results'
        }
    },
    
    // the fields config option will internally create an Ext.data.Model
    // constructor that provides mapping for reading the record data objects
    fields: [
        // map Record's 'firstname' field to data object's key of same name
        {name: 'name'},
        // map Record's 'job' field to data object's 'occupation' key
        {name: 'job', mapping: 'occupation'}
    ],
});

Ext.data.StoreのデータにJSONデータを流しこむためにExt.data.JsonReader(type: 'json')を使っている
っていうサンプルなんですが、

root: 'rows'

っていう記述によって、JSONデータのrowsが持ってる配列をデータとして認識して、
取り込めるわけなんです。

ところがですよ

JSONデータの階層が深くなって

{
    response: {
        results: 2000, // Reader's configured totalProperty
        rows: [        // Reader's configured root
            // record data objects:
            { id: 1, firstname: 'Bill', occupation: 'Gardener' },
            { id: 2, firstname: 'Ben' , occupation: 'Horticulturalist' },
            ...
        ]
    }
}

とか階層が深くなると、

root: 'rows'

って書いてもダメだったりする。

サンプルを探した

1階層目を持ってくるサンプルしかなかった。

Sencha Touchのソースを読んだ

結果、ここが重要らしいというところにたどり着いた。

    createAccessor : function() {
        var re = /[\[\.]/;
        
        return function(expr) {
            if (Ext.isEmpty(expr)) {
                return Ext.emptyFn;
            }
            if (Ext.isFunction(expr)) {
                return expr;
            }
            var i = String(expr).search(re);
            if (i >= 0) {
                return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
            }
            return function(obj) {
                return obj[expr];
            };
        };
    }()

alertデバッグした結果、exprにはrootで指定したものが入ってくることが分かったので、
rootに'['か'.'があれば、良いらしいことまで分かった。
で、色々試行錯誤した末に、

root: '["response"]["rows"]'

って書いたら動いた。

Google先生はえらい

書いてる途中にアレと思ってググったら、答えがあった(汗
ExtJS HttpProxy+XmlReaderのサンプル

root: ‘results.usedcar’,

って書いてるわけですよ。
つまり、上の例で言えば、

root: 'response.rows'

でも良かったわけですね。実際これで動きました。
だから、"rootに'['か'.'があれば"という判定だったわけですね。
納得。


ていうかこのサイト、中の人がやってるのか。
どうりで詳しいわけだw

サンプルコード

Stack Stock Booksの自分のアカウントのいつか欲しいをAPIJSONP形式で持ってきて、
一覧表示するアプリケーションです。

http://jsdo.it/taka_2/gAay