I'm trying (and trying...) to get my JsonStore object parse JSON stream that has MetaData included along accompanying data, but I'm obviously doing something wrong :) Following request gets valid JSON stream out of Jayrock's JSON-RPC sitting at the server side:
var params = {
id: 1, // Jayrock's JSON-RPC expects this identifier
method: 'getData', // Method name pypi2pkgsys - Google Code:: 'FuXi' 'Download FuXi failed: MD5 validation failed for FuXi-0.95b.dev-r229.tar. gz; possible download problem?' 'FurcTools' 'Download FurcTools failed: None http://code.google.com/p/pypi2pkgsys/source/browse/trunk/pypi2pkgsys/patches/pypi2pkgsys.log?r=118HOME |
params: {
featureSourceName: 'GisServer', // Params to my getData method
className: 'Road',
propertyName: 'StreetName',
isGrouped: 1,
isOrdered: 1
}
}
// Asynchronous request follows...
Ext.Ajax.request({
url: 'http://.../jsonService.ashx', // An URL to Jarock-backed web service
params: Ext.encode(params),
success: function(response) {successCallbackFn(response)},
failure: function(response) {failureCallbackFn(response)}
});
Response.responseText returned to successCallbackFn() function looks like this (formatted for easier reading) - it carries MetaData definition along the data:
{
"id":1,
"result":{
"metaData":{
"root":"fields",
"id":"StreetName",
"fields":[
{"name":"StreetName","type":"string"}
]
},
"results":307,
"fields":[
{"StreetName":"1st Street"},
{"StreetName":"2nd Street"},
{...}
]
}
}
Now I'm stuck. How do I instantiate a valid JsonStore using received JSON stream?
function successCallbackFn(response){ 2007-03-06 - JotSpot Wiki (dojo):: Quick status on implementation of fetch and find sorting APIs as decided on .. <wild_bill> not only that. you are going to get a stream of queries from http://dojo.jot.com/2007-03-06HOME |
var o = eval('('+response.responseText+')');
if(o){
if(o.result.metaData && o.result.fields){
...How do I get a valid JsonStore object here?...
}
}
Regards,
Maksim Sestic
Condor,
Thanks for the tip. I already tried it the easier way but had to resort to step-by-step approach since I couldn't get my params passed to underlying HttpProxy:
var params = {
id: 1,
method: 'getData',
params: {
featureSourceName: 'GisServer',
className: 'Road',
propertyName: 'StreetName',
isGrouped: 1,
isOrdered: 1
}
}
var store = new Ext.data.JsonStore({
url: 'http://.../jsonService.ashx',
params: Ext.encode(params),
listeners: {
loadexception: function(proxy, store, response, e) {
failureCallbackFn(response);
}
}
});
store.load();
I simply have no idea why instantiated store in above example wouldn't read params - underlying HttpProxy simply ignores them. I also tried with baseParams instead of params config directive, but with no success.
Regards,
Maksim Sestic
Regarding my previous post - I've just inspected official JSON-RPC specification (http://json-rpc.org/wiki/specification) and have to admit that Jayrock's JSON-RPC was implemented by the standard. It says:
1.1 Request (method invocation)
A remote method is invoked by sending a request to a remote service. The request is a single object serialized using JSON.
It has three properties:
method - A String containing the name of the method to be invoked.
params - An Array of objects to pass as arguments to the method.
id - The request id. This can be of any type. It is used to match the response with the request that it is replying to.
1.2 Response
When the method invocation completes, the service must reply with a response. The response is a single object serialized using JSON.
It has three properties:
result - The Object that was returned by the invoked method. This must be null in case there was an error invoking the method.
error - An Error object if there was an error invoking the method. It must be null if there was no error.
id - This must be the same id as the request it is responding to.
So, there it is - both id and result root nodes in response stream :)... It's due to the present state of existing ExtJS classes: both JsonReader and JsonStore were not designed with JSON-RPC in mind. I guess ExtJS needs JsonRpcReader and JsonRpcStore objects to fully implement said standard.
Regards,
Maksim Sestic
That response can't be processed; metaData needs to be a root property, e.g.
{
"id":1,
"metaData":{
"root":"fields",
"id":"StreetName",
"fields":[ Changeset 897 - mapfish - Trac:: trunk/MapFish/server/java/print/print-standalone/samples/spec.json (modified) (2 diffs) .. JsonStore({. 643, root: "layouts",. 644, fields: ['name'], http://trac.mapfish.org/trac/mapfish/changeset/897HOME | Python Package Index : Index of Packages Matching 'object':: jsonstore 0.3, 2, A RESTful exposed database for arbitrary JSON objects. . It also provides a basic implementation of generic functions in Zope3 http://pypi.python.org/pypi?:action=search&term=objectHOME |
{"name":"StreetName","type":"string"}
]
},
"result":{
"results":307,
"fields":[
{"StreetName":"1st Street"},
{"StreetName":"2nd Street"},
{...}
]
}
}
A Store contains a proxy and a reader. The proxy retrieves the data, the reader processes it and stores the records in the store.
Why are you doing the Ajax call yourself instead of letting the proxy handle it?
Example:
var store = new Ext.data.JsonStore({
url: 'http://.../jsonService.ashx',
listeners: {
loadexception: function(proxy, store, response, e) {
failureCallbackFn(response);
}
}
});
var params = {
id: 1,
method: 'getData',
params: {
featureSourceName: 'GisServer',
className: 'Road',
propertyName: 'StreetName',
isGrouped: 1,
isOrdered: 1
}
}
store.load({
'params': Ext.encode(params)
});
Condor, thanks fr pointing out which method of JsonReader should get overriden. Problem of wrong root node is actually caused by Jayrock's JSON-RPC. During serialization of a .NET object/class it automatically creates following root:
{
"id":1, // transaction Id, as passed via POST params
"result":{ // resulting dataset follows...
...
It's Jayrock's part, I didn't inject id and result nodes anywhere in my code. Somehow it's not possible to set this via JSON-RPC .NET class/method Attributes - I consider this behaviour a flaw in design. Of course, developers can inherit base JSON-RPC classes and implement their own JSON serialization/deserialization - which is an overkill after all. Anyways, I'll do my best to get it parsed on ExtJS side and post results here. :)
Regards,
Maksim Sestic
That is because Store expects an object as baseParams and params config options and not a string.
Instead use:
store.proxy.conn.jsonData = Ext.encode(params);
store.load();
Condor,
That was enlightning... :) still, it happens that loaded JsonStore has no data part in it, although debugger shows that response object returned was correct. If I understood your suggestion correctly:
var params = {
id: 1,
method: 'getData',
params: {
featureSourceName: 'GisServer',
className: 'Road',
propertyName: 'StreetName',
isGrouped: 1,
isOrdered: 1
}
}
var store = new Ext.data.JsonStore({
url: 'http://.../jsonService.ashx',
listeners: {
loadexception: function(proxy, store, response, e) {
failureCallbackFn(response);
}
}
});
store.proxy.conn.jsonData = Ext.encode(params);
Now, if store.load(); was issued here Response with both MetaData and Data part would get returned OK, but if I continue further a bit to actually see the data returned...
var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{id:'street', header: "Street name", width: 75, sortable: true, dataIndex: 'StreetName'}
],
stripeRows: true,
height:350,
width:600,
title:'JsonStore Grid',
renderTo: document.body
});
grid.render();
store.load();
This grid renders empty. If I click on it's header it throws:
this.fields has no properties
[Break on this error] var f = this.fields.get(fieldName);
I guess JsonStore is ignoring my data part for reasons unknown...
Regards,
Maksim Sestic
Allright, this override works for JsonReader (instantiated as JsonRpcReader, added JsonRpcStore to get to it):
read : function(response){
var json = response.responseText;
var o = eval("("+json+")");
if(!o.result) {
throw {message: "JsonRpcReader.read: Json object not found"};
}
if(o.result.metaData){
delete this.ef;
this.meta = o.result.metaData;
this.recordType = Ext.data.Record.create(o.result.metaData.fields);
this.onMetaChange(this.meta, this.recordType, o);
}
return this.readRecords(o.result);
}
Where JsonRpcStore gets instantiated via:
var store = new Ext.data.JsonRpcStore({
url: 'http://.../jsonService.ashx'
});
store.proxy.conn.jsonData = params;
I think of it as of a partial solution to the problem since I don't fully understand inner workings of neither JsonReader nor JsonStore (read - a newbie). I.e. I don't know if separate instantiation of JsonRpcReader would work properly, or if widgets would work with JsonRpcStore as expected. Grid using JsonRpcStore, though, works OK.
Regards,
Maksim Sestic
Did you check with Firebug if the request and response are correct?
ps. Looking at it more closely you don't even need Ext.encode, e.g.
store.proxy.conn.jsonData = params;
store.load();
Man, now I'm stuck... JSON stream was actually returned by Jayrock's JSON-RPC. I guess I have two options available - to somehow make JSON-RPC return what's actually consumable, or parse response.responseText using ExtJS and get that JSON stream right. Being an ExtJS novice as I am, off I go to .NET to see what Jayrock's JSON-RPC can do about it :)
Regards,
Maksim Sestic
The following override lets you change the location of the metaData property:
Ext.override(Ext.data.JsonReader, {
metaDataProperty: 'metaData',
read : function(response){
var json = response.responseText;
var o = eval("("+json+")");
if(!o) {
throw {message: "JsonReader.read: Json object not found"};
}
var metaData = this.getJsonAccessor(metaDataProperty)(o);
if(metaData){
delete this.ef;
this.meta = metaData;
this.recordType = Ext.data.Record.create(metaData.fields);
this.onMetaChange(this.meta, this.recordType, o);
}
return this.readRecords(o);
}
});
Usage:
var store = new Ext.data.JsonStore({...});
store.reader.metaDataProperty = 'result.metaData';
store.load();
ps. You setting for root is wrong, it should be 'result.fields'.
Firebug says it's OK, here's copy/paste + additional formatting from it's Console:
POST http://.../jsonService.ashx?_dc=1200757177381& (672ms)ext-base.js (line 10)
This ?_dc parameter has been added by underlying HttpProxy I guess... Then:
POST part:
{
"id":1,
"method":"getData",
"params":{
"featureSourceName":"GisServer",
"className":"Road",
"propertyName":"StreetName",
"isGrouped":1,
"isOrdered":1
}
}
RESPONSE part:
{
"id":1,
"result":{
"metaData":{
"root":"fields",
"id":"StreetName",
"fields":[
{"name":"StreetName","type":"string"}
]
},
"results":307,
"fields":[
{"StreetName":"1st Street"},
{"StreetName":"2nd Street"},
{...}
]
}
}
There're actually 307 records returned. There's only one field of type 'string' named 'StreetName' - MetaData 'id' property is set to that exact field since it's unique. I guess there's something wrong with my data returned... but it seems so OK to me from this perspective.
Regards,
Maksim Sestic
Red Hat's Rough Recovery From CFO Exit
Windows Live Finds a New, Pre-installed Home
|