PDA

View Full Version : JsonReader with Complex Array - Guarantee Selection?



antonye
13 Jun 2011, 4:23 AM
I'm struggling with mapping complex JSON to my grid.

My JSON looks something like this:



{
"item": 1,
"subitems": [
{ "subitem": 1, "value": "A" },
{ "subitem": 2, "value": "B" },
{ "subitem": 3, "value": "C" }
]
}


Now I have managed to map this in my JsonReader with a piece of code mentioned by animal, as sometimes my "subitems" element can be null but I want to show the values in my expansion pane.



{ name: 'flatten_a', type: 'string', mapping: 'subitems? obj.subitems[0].value : "n/a";'},
{ name: 'flatten_b', type: 'string', mapping: 'subitems? obj.subitems[1].value : "n/a";'},
{ name: 'flatten_c', type: 'string', mapping: 'subitems? obj.subitems[2].value : "n/a";'}


That all works fine...

BUT, being the careful programmer that I am (!!) I want to GUARANTEE which items I am selecting out of the array, as the data that I am being passed may not be guaranteed to always be in the same order.

Essentially I am trying do a kind of "WHERE" clause on selecting the index of the array, like:



obj.subitems[ (obj.subitems.index WHERE obj.subitems.subitem == 1) ].value


The ExtJS API docs for 3.2 (the version we have) doesn't cover any kind of complex mapping within the Ext.data.Record object, so I'm kind of stumped.

Anyone got any hints?

skirtle
13 Jun 2011, 4:40 PM
What you're effectively doing here is an injection attack on a JsonReader. Take a look at the source for the method createAccessor() to understand why that trick works. The code you have currently looks like this post-injection:


function() {
return obj.subitems ? obj.subitems[0].value : "n/a";
}

where obj is an object extracted from the JSON. You can do much more complicated things along the same lines but recent versions of Ext support mapping functions, which make this pretty easy to do without resorting to tricks:


{
name: 'name',
mapping: function(obj) {
var si = obj.subitems, len = si.length, index = 0;

for ( ; index < len ; ++index) {
if (si[index].subitem === 1) {
return si[index].value;
}
}

return 'n/a';
}
}

antonye
14 Jun 2011, 1:01 AM
That's brilliant, thank-you, exactly what I was looking for!

As I said, the API docs are lacking in detail for the data.Record object, especially when it comes to what can be done with the mapping.

It would be great if some more advanced examples could be included in the official docs going forward.

skirtle
14 Jun 2011, 4:06 PM
As I said, the API docs are lacking in detail for the data.Record object, especially when it comes to what can be done with the mapping.

You can only get so far relying on the docs, you need to read the source code.