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