Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Json.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-data.reader.Json'>/**
2 </span> * @author Ed Spencer
3  * @class Ext.data.reader.Json
4  * @extends Ext.data.reader.Reader
5  * 
6  * &lt;p&gt;The JSON Reader is used by a Proxy to read a server response that is sent back in JSON format. This usually
7  * happens as a result of loading a Store - for example we might create something like this:&lt;/p&gt;
8  * 
9 &lt;pre&gt;&lt;code&gt;
10 Ext.define('User', {
11     extend: 'Ext.data.Model',
12     fields: ['id', 'name', 'email']
13 });
14
15 var store = new Ext.data.Store({
16     model: 'User',
17     proxy: {
18         type: 'ajax',
19         url : 'users.json',
20         reader: {
21             type: 'json'
22         }
23     }
24 });
25 &lt;/code&gt;&lt;/pre&gt;
26  * 
27  * &lt;p&gt;The example above creates a 'User' model. Models are explained in the {@link Ext.data.Model Model} docs if you're
28  * not already familiar with them.&lt;/p&gt;
29  * 
30  * &lt;p&gt;We created the simplest type of JSON Reader possible by simply telling our {@link Ext.data.Store Store}'s 
31  * {@link Ext.data.proxy.Proxy Proxy} that we want a JSON Reader. The Store automatically passes the configured model to the
32  * Store, so it is as if we passed this instead:
33  * 
34 &lt;pre&gt;&lt;code&gt;
35 reader: {
36     type : 'json',
37     model: 'User'
38 }
39 &lt;/code&gt;&lt;/pre&gt;
40  * 
41  * &lt;p&gt;The reader we set up is ready to read data from our server - at the moment it will accept a response like this:&lt;/p&gt;
42  * 
43 &lt;pre&gt;&lt;code&gt;
44 [
45     {
46         &quot;id&quot;: 1,
47         &quot;name&quot;: &quot;Ed Spencer&quot;,
48         &quot;email&quot;: &quot;ed@sencha.com&quot;
49     },
50     {
51         &quot;id&quot;: 2,
52         &quot;name&quot;: &quot;Abe Elias&quot;,
53         &quot;email&quot;: &quot;abe@sencha.com&quot;
54     }
55 ]
56 &lt;/code&gt;&lt;/pre&gt;
57  * 
58  * &lt;p&gt;&lt;u&gt;Reading other JSON formats&lt;/u&gt;&lt;/p&gt;
59  * 
60  * &lt;p&gt;If you already have your JSON format defined and it doesn't look quite like what we have above, you can usually
61  * pass JsonReader a couple of configuration options to make it parse your format. For example, we can use the 
62  * {@link #root} configuration to parse data that comes back like this:&lt;/p&gt;
63  * 
64 &lt;pre&gt;&lt;code&gt;
65 {
66     &quot;users&quot;: [
67        {
68            &quot;id&quot;: 1,
69            &quot;name&quot;: &quot;Ed Spencer&quot;,
70            &quot;email&quot;: &quot;ed@sencha.com&quot;
71        },
72        {
73            &quot;id&quot;: 2,
74            &quot;name&quot;: &quot;Abe Elias&quot;,
75            &quot;email&quot;: &quot;abe@sencha.com&quot;
76        }
77     ]
78 }
79 &lt;/code&gt;&lt;/pre&gt;
80  * 
81  * &lt;p&gt;To parse this we just pass in a {@link #root} configuration that matches the 'users' above:&lt;/p&gt;
82  * 
83 &lt;pre&gt;&lt;code&gt;
84 reader: {
85     type: 'json',
86     root: 'users'
87 }
88 &lt;/code&gt;&lt;/pre&gt;
89  * 
90  * &lt;p&gt;Sometimes the JSON structure is even more complicated. Document databases like CouchDB often provide metadata
91  * around each record inside a nested structure like this:&lt;/p&gt;
92  * 
93 &lt;pre&gt;&lt;code&gt;
94 {
95     &quot;total&quot;: 122,
96     &quot;offset&quot;: 0,
97     &quot;users&quot;: [
98         {
99             &quot;id&quot;: &quot;ed-spencer-1&quot;,
100             &quot;value&quot;: 1,
101             &quot;user&quot;: {
102                 &quot;id&quot;: 1,
103                 &quot;name&quot;: &quot;Ed Spencer&quot;,
104                 &quot;email&quot;: &quot;ed@sencha.com&quot;
105             }
106         }
107     ]
108 }
109 &lt;/code&gt;&lt;/pre&gt;
110  * 
111  * &lt;p&gt;In the case above the record data is nested an additional level inside the &quot;users&quot; array as each &quot;user&quot; item has
112  * additional metadata surrounding it ('id' and 'value' in this case). To parse data out of each &quot;user&quot; item in the 
113  * JSON above we need to specify the {@link #record} configuration like this:&lt;/p&gt;
114  * 
115 &lt;pre&gt;&lt;code&gt;
116 reader: {
117     type  : 'json',
118     root  : 'users',
119     record: 'user'
120 }
121 &lt;/code&gt;&lt;/pre&gt;
122  * 
123  * &lt;p&gt;&lt;u&gt;Response metadata&lt;/u&gt;&lt;/p&gt;
124  * 
125  * &lt;p&gt;The server can return additional data in its response, such as the {@link #totalProperty total number of records} 
126  * and the {@link #successProperty success status of the response}. These are typically included in the JSON response
127  * like this:&lt;/p&gt;
128  * 
129 &lt;pre&gt;&lt;code&gt;
130 {
131     &quot;total&quot;: 100,
132     &quot;success&quot;: true,
133     &quot;users&quot;: [
134         {
135             &quot;id&quot;: 1,
136             &quot;name&quot;: &quot;Ed Spencer&quot;,
137             &quot;email&quot;: &quot;ed@sencha.com&quot;
138         }
139     ]
140 }
141 &lt;/code&gt;&lt;/pre&gt;
142  * 
143  * &lt;p&gt;If these properties are present in the JSON response they can be parsed out by the JsonReader and used by the
144  * Store that loaded it. We can set up the names of these properties by specifying a final pair of configuration 
145  * options:&lt;/p&gt;
146  * 
147 &lt;pre&gt;&lt;code&gt;
148 reader: {
149     type : 'json',
150     root : 'users',
151     totalProperty  : 'total',
152     successProperty: 'success'
153 }
154 &lt;/code&gt;&lt;/pre&gt;
155  * 
156  * &lt;p&gt;These final options are not necessary to make the Reader work, but can be useful when the server needs to report
157  * an error or if it needs to indicate that there is a lot of data available of which only a subset is currently being
158  * returned.&lt;/p&gt;
159  */
160 Ext.define('Ext.data.reader.Json', {
161     extend: 'Ext.data.reader.Reader',
162     alternateClassName: 'Ext.data.JsonReader',
163     alias : 'reader.json',
164     
165     root: '',
166     
167 <span id='Ext-data.reader.Json-cfg-record'>    /**
168 </span>     * @cfg {String} record The optional location within the JSON response that the record data itself can be found at.
169      * See the JsonReader intro docs for more details. This is not often needed and defaults to undefined.
170      */
171     
172 <span id='Ext-data.reader.Json-cfg-useSimpleAccessors'>    /**
173 </span>     * @cfg {Boolean} useSimpleAccessors True to ensure that field names/mappings are treated as literals when
174      * reading values. Defalts to &lt;tt&gt;false&lt;/tt&gt;.
175      * For example, by default, using the mapping &quot;foo.bar.baz&quot; will try and read a property foo from the root, then a property bar
176      * from foo, then a property baz from bar. Setting the simple accessors to true will read the property with the name 
177      * &quot;foo.bar.baz&quot; direct from the root object.
178      */
179     useSimpleAccessors: false,
180     
181 <span id='Ext-data.reader.Json-method-readRecords'>    /**
182 </span>     * Reads a JSON object and returns a ResultSet. Uses the internal getTotal and getSuccess extractors to
183      * retrieve meta data from the response, and extractData to turn the JSON data into model instances.
184      * @param {Object} data The raw JSON data
185      * @return {Ext.data.ResultSet} A ResultSet containing model instances and meta data about the results
186      */
187     readRecords: function(data) {
188         //this has to be before the call to super because we use the meta data in the superclass readRecords
189         if (data.metaData) {
190             this.onMetaChange(data.metaData);
191         }
192
193 <span id='Ext-data.reader.Json-property-jsonData'>        /**
194 </span>         * DEPRECATED - will be removed in Ext JS 5.0. This is just a copy of this.rawData - use that instead
195          * @property jsonData
196          * @type Mixed
197          */
198         this.jsonData = data;
199         return this.callParent([data]);
200     },
201
202     //inherit docs
203     getResponseData: function(response) {
204         try {
205             var data = Ext.decode(response.responseText);
206         }
207         catch (ex) {
208             Ext.Error.raise({
209                 response: response,
210                 json: response.responseText,
211                 parseError: ex,
212                 msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
213             });
214         }
215         //&lt;debug&gt;
216         if (!data) {
217             Ext.Error.raise('JSON object not found');
218         }
219         //&lt;/debug&gt;
220
221         return data;
222     },
223
224     //inherit docs
225     buildExtractors : function() {
226         var me = this;
227         
228         me.callParent(arguments);
229
230         if (me.root) {
231             me.getRoot = me.createAccessor(me.root);
232         } else {
233             me.getRoot = function(root) {
234                 return root;
235             };
236         }
237     },
238     
239 <span id='Ext-data.reader.Json-method-extractData'>    /**
240 </span>     * @private
241      * We're just preparing the data for the superclass by pulling out the record objects we want. If a {@link #record}
242      * was specified we have to pull those out of the larger JSON object, which is most of what this function is doing
243      * @param {Object} root The JSON root node
244      * @return {Array} The records
245      */
246     extractData: function(root) {
247         var recordName = this.record,
248             data = [],
249             length, i;
250         
251         if (recordName) {
252             length = root.length;
253             
254             for (i = 0; i &lt; length; i++) {
255                 data[i] = root[i][recordName];
256             }
257         } else {
258             data = root;
259         }
260         return this.callParent([data]);
261     },
262
263 <span id='Ext-data.reader.Json-method-createAccessor'>    /**
264 </span>     * @private
265      * Returns an accessor function for the given property string. Gives support for properties such as the following:
266      * 'someProperty'
267      * 'some.property'
268      * 'some[&quot;property&quot;]'
269      * This is used by buildExtractors to create optimized extractor functions when casting raw data into model instances.
270      */
271     createAccessor: function() {
272         var re = /[\[\.]/;
273         
274         return function(expr) {
275             if (Ext.isEmpty(expr)) {
276                 return Ext.emptyFn;
277             }
278             if (Ext.isFunction(expr)) {
279                 return expr;
280             }
281             if (this.useSimpleAccessors !== true) {
282                 var i = String(expr).search(re);
283                 if (i &gt;= 0) {
284                     return Ext.functionFactory('obj', 'return obj' + (i &gt; 0 ? '.' : '') + expr);
285                 }
286             }
287             return function(obj) {
288                 return obj[expr];
289             };
290         };
291     }()
292 });</pre></pre></body></html>