PDA

View Full Version : [OPEN-58][3.0+] JsonReader with array data



Condor
26 Aug 2009, 6:23 AM
A JsonReader processes the root incorrectly when reading array data, e.g.

var reader = new Ext.data.JsonReader({
root: 'root',
idProperty: '0',
fields: [
{name: 'value', mapping: '0'},
{name: 'text', mapping: '1'}
]
});
console.log(reader.readRecords({
root: [
[1, 'One'],
[2, 'Two'],
[3, 'Three']
]
}));
will show a single record with value:1 and text:'2,Two'.

The problem is that Ext.data.DataReader.isData incorrectly identifies the root as data. I suggest adding:

Ext.override(Ext.data.DataReader, {
isData : function(data) {
return (data && Ext.isObject(data) && !Ext.isArray(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
}
});

Note:
Yes, I know this can also be done with an ArrayReader, but my existing code uses JsonReader because ArrayReader didn't support a root config option (which it does now).


Extra bug for Ext 3.0.1:
The getJsonAccessor method in JsonReader has been replaced with the createAccessor method, but ArrayReader still uses the (now undefined) getJsonAccessor method.

Also, ArrayReader doesn't support the successProperty and messageProperty config options of JsonReader.

Animal
26 Aug 2009, 7:15 AM
There should be no such thing as ArrayReader.

Mappings may be either numbers or strings, but they are still used as Array subscripts, so there is no logical difference between an ArrayReader and a JsonReader!

Save some code here guys!

Condor
26 Aug 2009, 7:28 AM
I completely agree (I even posted a FR for it).

Suggested change for ArrayReader:

Ext.override(Ext.data.JsonReader, {
getDefaultMapping: function(field, index){
return field.name;
},
dataProperty: 'jsonData',
buildExtractors : function() {
if(this.ef){
return;
}
var s = this.meta, Record = this.recordType,
f = Record.prototype.fields, fi = f.items, fl = f.length;
if(s.totalProperty) {
this.getTotal = this.createAccessor(s.totalProperty);
}
if(s.successProperty) {
this.getSuccess = this.createAccessor(s.successProperty);
}
if (s.messageProperty) {
this.getMessage = this.createAccessor(s.messageProperty);
}
this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
if (s.id || s.idProperty) {
var g = this.createAccessor(s.id || s.idProperty);
this.getId = function(rec) {
var r = g(rec);
return (r === undefined || r === '') ? null : r;
};
} else {
this.getId = function(){return null;};
}
var ef = [];
for(var i = 0; i < fl; i++){
f = fi[i];
var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : this.getDefaultMapping(f, i);
ef.push(this.createAccessor(map));
}
this.ef = ef;
},
readRecords : function(o){
this[this.dataProperty] = o;
if(o.metaData){
this.onMetaChange(o.metaData);
}
var s = this.meta, Record = this.recordType,
f = Record.prototype.fields, fi = f.items, fl = f.length, v;
var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
if(s.totalProperty){
v = parseInt(this.getTotal(o), 10);
if(!isNaN(v)){
totalRecords = v;
}
}
if(s.successProperty){
v = this.getSuccess(o);
if(v === false || v === 'false'){
success = false;
}
}
return {
success : success,
records : this.extractData(root, true),
totalRecords : totalRecords
};
}
});
Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
getDefaultMapping: function(field, index){
return index;
},
dataProperty: 'arrayData'
});

Animal
26 Aug 2009, 9:24 AM
It should be even smaller than that. I have it as 16 lines including API docs.

http://extjs.com/forum/showthread.php?p=334151#post334151

Condor
26 Aug 2009, 9:30 AM
It's identical (your JsonReader is a bit bigger).

Animal
26 Aug 2009, 9:42 AM
Ah, yes, sorry. I read your "suggestion for ArrayReader", and assumed that whole code below block was it - the ArrayReader! Yes, that is the way to go

Condor
26 Aug 2009, 10:44 PM
The getJsonAccessor method in JsonReader has been replaced with the createAccessor method, but ArrayReader still uses the (now undefined) getJsonAccessor method.

Also, ArrayReader doesn't support the successProperty and messageProperty config options of JsonReader.

All good reasons to refactor ArrayReader (http://extjs.com/forum/showthread.php?t=69453).

evant
27 Aug 2009, 1:06 AM
Looks ok. At a glance I think Condors code might need a bit extra to be able to specify an array subscripts for the id.

Condor
20 Oct 2009, 2:43 AM
Can the original problem (reading array data with a JsonReader) be fixed?

The refactoring stuff has its own feature request thread.