Wow, it’s been a while since I posted something…
I’ve been working a lot with ExtJs recently, as the basis for a web application which talks to a lot of JSON-based web services. And I got to say that I am enjoying it – it’s a nice, powerful framework that makes working with JavaScript quite bearable.
ExtJs includes a sub-framework for turning JSON (or XML) data into ‘models’, including nested data. It does this by providing ‘reader‘ classes that understand JSON (or XML). However, it only understands nested arrays. Sometimes what you have is a nested object – e.g. when you serialize a HashMap from Java into JSON. Fortunately, it’s possible to extend ExtJS and provide a new Reader – one that understands nested objects (aka ‘maps’, or ‘hashes’, or ‘associative arrays’).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A variant of the JSON reader. Instead of reading arrays, where each record in the array field | |
* has an 'id' property, it reads objects – aka associative arrays. The key of the entry will be the | |
* array. | |
* | |
* So where the JSON reader would like data like this: | |
* [ { id: '1', property: 'foo' }, { id: '2', property: 'bar' } ] | |
* | |
* the associative reader likes data like this: | |
* { '1': { property: 'foo' }, '2': { property: 'bar' } } | |
*/ | |
Ext.define('Twasink.data.AssociativeReader', { | |
extend: 'Ext.data.reader.Json', | |
alias: 'reader.associative', | |
readRecords: function(data) { | |
// convert the associative array into a normal array. | |
var idProperty = 'id'; // should be a config value? | |
var arrayData = [] | |
Ext.Object.each(data, function(key, value) { | |
var arrayEntry = {}; | |
Ext.Object.merge(arrayEntry, value); | |
arrayEntry[idProperty] = key; | |
arrayData.push(arrayEntry); | |
}); | |
return this.callParent( [ arrayData ]); | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ext.define('Twasink.model.Bar', { | |
extend: 'Ext.data.Model', | |
idProperty: 'id', | |
fields: [ 'baz', 'bux'] | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ "id": "foo_1", "baz": "baz_1", "bux": "bux_1", "bar": { | |
"bar_1": { "baz": "bar_baz_1", "bux": "bar_bux_1" }, | |
"bar_2": { "baz": "bar_baz_2", "bux": "bar_bux_2" } | |
} | |
}, | |
{ "id": "foo_2", "baz": "baz_2", "bux": "bux_2", "bar": { | |
"bar_1": { "baz": "bar_baz_3", "bux": "bar_bux_3" }, | |
"bar_2": { "baz": "bar_baz_4", "bux": "bar_bux_4" } | |
} | |
} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ext.define('Twasink.model.Foo', { | |
extend: 'Ext.data.Model', | |
requires: [ 'Twasink.data.AssociativeReader', 'Twasink.model.Bar' ], | |
idProperty: 'id', | |
fields: [ 'baz', 'bux'], | |
hasMany: [ { model: 'Twasink.model.Bar', name: 'bars', associationKey: 'bar', reader: 'associative' }] | |
}) |
If you’re using ExtJS, I hope you find this useful.