PDA

View Full Version : JsonReader & Record mapping?



willogee
2 Mar 2007, 10:51 AM
Hi there

Am I right that to use the JsonReader the JSON must be derived from an associative array of data and that the mapping specified in the Ext.data.Record points to the keys in the associative array?

If that's so then it seems somewhat wasteful to have array keys in every row of data returned by the server; wasn't the whole point of JSON to have a lean data format so that transporting between server & client would be at it's most efficient (e.g. versus xml).

I'm wondering if it's possible to have the Ext.data.Record point to a index of columns instead of effectively pointing to column names (i.e. the array keys)?

I admit that in a paged grid context, the amount of data being shipped by the server at a time is small, but for grids displaying large datasets at once, it might become an issue.

Or am I missing something altogether?

Thanks for any thoughts on this.
Will

JeffHowden
2 Mar 2007, 11:10 AM
You know, I had the very same idea when I first started messing about with JSON. Not only did I want to come up with a leaner data format, but I want to be able to access the data in a manner I was familiar with in my application-server language of choice -- ColdFusion. So, for a JSON packet that represents a query, that looks like:


{"recordcount": 3, "data": [
{"owned_by":"Jeff Howden","name":"Administrators","description":"Site administrators","id":1,"is_active":1,"users":3}
, {"owned_by":"Jeff Howden","name":"Demo Users","description":"Group of users given demo access to the system.","id":2,"is_active":1,"users":1}
, {"owned_by":"Jeff Howden","name":"Super Administrators","description":"Administrators of the overall system.","id":3,"is_active":1,"users":3}
]}

I thought it'd be much better suited as:


{"recordcount": 3, "data": {
id: [1, 2, 3]
, name: ["Administrators", "Demo Users", "Super Administrators"]
, description: ["Site administrators", "Group of users given demo access to the system.", "Administrators of the overall system."]
, is_active: [1, 1, 1]
, users: [3, 1, 3]
, owned_by: ["Jeff Howden", "Jeff Howden", "Jeff Howden"]
}}

But, alas, the JSON format stipulates that this sort of data "must" be an array of objects.

Animal
2 Mar 2007, 11:24 AM
If you returned data like this rather than an object with an Array of rows, each of which is an object with named properties:



{total:2,root:[["r1c1","r1c2"],["r2c1","r2c2"]]}


Then you could just use a numeric dataIndex property in your ColumnModel, and a numeric name property in your Record.

I think... I'd have to try it. At worst, you might have to write a custom Reader...

tryanDLS
2 Mar 2007, 11:29 AM
While at 1st glance, it might appear that your 'transposed' data structure is better/more efficient, etc, consider what it would take to build that from the server side, when you're querying a database and processing a resultset row-by-row. While you save some bytes because you eliminated repeated instances of the labels, you've complicated everything else. The performance gains from using JSON vs XML come from
a) smaller footprint b/c you don't have closing tags on every data element. You might say that you could build your XML with attributes instead of elements and save the closing tags, but this is problematic in a lot of backend processes - they like to serialize to elements, not attributes.
b) the fact that you don't have to parse the XML into a DOM and navigate the DOM tree - javascript handling of the object literal is very quick.
c) the fact that you can differentiate data types in JSON (e.g string vs number) without adding additional attributes or a DTD.

If you wanted to optimize further, you could do it by minimizing your label length and making use of the mapping features of the Record/Store/ColumnModel to create the friendly names on the client side. This would of course add another dependency between the client/server, but if bandwidth was the driving concern, it might save you some bytes.

Animal
2 Mar 2007, 11:41 AM
A working example to drop in the /examples/grid directory:



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Json Grid Example</title>

<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../yui-utilities.js"></script>
<script type="text/javascript" src="../../ext-yui-adapter.js"></script>
<script type="text/javascript" src="../../ext-all-debug.js"></script>
<link rel="stylesheet" type="text/css" href="grid-examples.css" />


<link rel="stylesheet" type="text/css" href="../examples.css" />
</head>
<script type="text/javascript">
function createGrid(data) {
var guests = Ext.data.Record.create([
{name: 0},
{name: 1},
{name: 2}
]);

// create reader that reads into Topic records
var reader = new Ext.data.JsonReader({
totalProperty: 'total',
root: 'root',
id: '0'
}, guests);

// create the Data Store
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: reader,
remoteSort: true
});
ds.setDefaultSort('guest', 'desc');

var cm = new Ext.grid.ColumnModel([
{
header:'Guest',
dataIndex:0
},
{
header:'Attending Ceremony',
dataIndex:1,
},
{
header:'Attending Reception',
dataIndex:2,
}]);

// create the editor grid
var grid = new Ext.grid.Grid('container', {
ds: ds,
cm: cm,
selModel: new Ext.grid.RowSelectionModel({singleSelect:true}),
enableColLock:true
});

// render it
ds.load();
grid.render();
}
Ext.onReady(function() {
createGrid({total:2,root:[[false,"Lily Tran",false],[false,"Alfred Wong",false]]});
});
</script>
</head>
<body>
<div id="container" style="height:200px;width:500px"></div>
</body>

JeffHowden
2 Mar 2007, 11:47 AM
While at 1st glance, it might appear that your 'transposed' data structure is better/more efficient, etc, consider what it would take to build that from the server side, when you're querying a database and processing a resultset row-by-row.

Actually, in ColdFusion, it's definitely quicker to dump using the objects of arrays approach in my last post. Regardless of the language though, in order to dump a query object to JSON (either format), you'd still have to process the resultset row-by-row (whether by hand or by the JSON encoding function).

jack.slocum
2 Mar 2007, 1:03 PM
Ummm sorry to come in so late guys, but is there any reason you can't use an ArrayReader? :D

Animal
2 Mar 2007, 11:41 PM
An ArrayReader can't handle paged data - it assumes the array is the whole dataset.

With the JsonReader, it has the "totalProperty" option.

jack.slocum
3 Mar 2007, 2:17 PM
Well, that a good reason. :)

markn
30 Apr 2007, 5:51 AM
I just saw (and used) BufferedMemoryProxy to put Paging though Arrays in practise. Worked a treat.


http://extjs.com/forum/showthread.php?t=3793&page=2&highlight=paging+ArrayReader+load

mihg
10 Oct 2007, 7:11 AM
I thought this might be useful ... hopefully I've put it in the right thread.

If someone was wandering how to iterate through complex n-dimensional arrays using JsonReader, here is some simple example code: It appears that after the first level of records you can access the rest of the records as JavaScript arrays.

Here is the Ext code:


Ext.onReady(function(){


var ds = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: 'test.php'}),
reader: new Ext.data.JsonReader({
totalProperty: 'total',
root: 'rows',
id: 'id'
},['id','employer', 'employees'])
});

ds.load({callback:function(success){
if(success){
alert('count:'+ds.getCount());
//alert(ds.getAt(0).get('question'));
ds.each(function(r){
//alert(r.get('employees')+' count:'+r.get('employees').length);
emp_arr = r.get('employees');
for(i=0; i < emp_arr.length; i++){
alert(emp_arr[i]['firstname']);
}
});
}
}});


});



Here is the php code for test.php


<?php
$arr = array("total"=>3, "rows"=>array(array("id"=>"1", "employer"=>"IBM", "employees"=>array(array("firstname"=>"mike", "lastname"=>"h"), array("firstname"=>"joe", "lastname"=>"s"), array("firstname"=>"tom", "lastname"=>"j"))),
array("id"=>"2", "employer"=>"Microsoft", "employees"=>array(array("firstname"=>"microsoft-mike", "lastname"=>"h"), array("firstname"=>"microsoft-joe", "lastname"=>"s"), array("firstname"=>"microsoft-tom", "lastname"=>"j"))),
array("id"=>"3", "employer"=>"Oracle", "employees"=>array(array("firstname"=>"oracle-mike", "lastname"=>"h"), array("firstname"=>"oracle-joe", "lastname"=>"s"), array("firstname"=>"oracle-tom", "lastname"=>"j"))))
);
echo json_encode($arr);
?>

tuler
10 Oct 2007, 1:13 PM
Hi,

How about this even simpler data structure? An array of strings (or dates).


{"dates":["2007-09-14T00:00:00","2007-09-13T00:00:00","2007-09-12T00:00:00"],"totalCount":3}


Can I handle this with JsonReader/Record?

Thanks,
Danilo