Reading Associative Arrays with ExtJS Models

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’).

/**
* 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 ]);
}
})

view raw
AssociativeReader.js
hosted with ❤ by GitHub

Ext.define('Twasink.model.Bar', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [ 'baz', 'bux']
})

view raw
Bar.js
hosted with ❤ by GitHub

[
{ "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" }
}
}
]

view raw
example_data.json
hosted with ❤ by GitHub

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' }]
})

view raw
Foo.js
hosted with ❤ by GitHub

If you’re using ExtJS, I hope you find this useful.

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 20 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 22 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s