xJson Objects
Alright everyone, I have finished the xJSON object suite, or at least a decent first pass. This was a bigger project than I expected and I apologize for dragging it out over the past couple weeks. It seemed like every time I was about to finish, I would uncover a corner case that would break an entire second of the project. Anyway, I was away over the passed weekend and had to do a lot work in the evening last week, and missed your Tuesday post as well. I hope to be better about getting two articles written a week. I am also open to guest posts, if you are interest just leave a comment on any article.
Anyway, I have written the following objects: JsonObject, JsonArray, XJsonObject, and XJsonArray. Here they are:
/** * The JsonObject class manages a JSON object by creating getter and setters * * @namespace Core.Model * @class JsonObject * @dependencies library */ Core.Model.JsonObject = function(json) { this.update(json); }; Core.extend(Core.Model.JsonObject, Core.Model.Model, { /** * The number of values in the json object * * @property length * @type int */ length: 0, /** * Updates the object to use the passed data set * * @method update * @param json {array} jsonobject object * @public */ update: function(json) { // validation if (! isType(json, ‘object’)) {throw(’JsonObject - Invalid data passed into Update’);} this.parent.update.call(this, json); // private variables var data = {}, that = this, n = 0; var fx = function(key, o) { var ckey = capitalize(key); data[key] = Core.Model.XJson(o); that[(isType(o, ‘boolean’) && -1 !== key.indexOf(’is’))? key: ‘get’ + ckey] = function() {return data[key];}; that[’set’ + ckey] = function(o) { if ($type(o) !== $type(data[key])) {throw(’JSONObject - invalid object passed into setter for: ‘ + key);} data[key] = o; }; }; // iterate through the JSON object keys for (var key in json) { fx(key, json[key]); n += 1; }; // update public variables this.length = n; } }); /** * The JsonArray class manages … * * @namespace Core.Model * @class JsonArray * @dependencies library */ Core.Model.JsonArray = function(json) { this.update(json); }; Core.extend(Core.Model.JsonArray, Core.Model.Model, { /** * Boolean used to inform the ‘get’ method to clean the cache * * @property clean * @type boolean */ clean: false, /** * The number of values in the json array * * @property length * @type int */ length: 0, /** * Execute function ‘fn’ on all elements in collection * * @method batch * @param fn {function} the function to execute * @public */ batch: function(fn) { Core.batch(this.data, function(o, i, scope) { fn(scope.get(i), i); }, this); }, /** * Retrieve the element at ‘i’ from the collection; lazy definition to allow for converting objects on demand * * @method get * @param i {int} index in the data * @public */ get: function(i) { var that = this, data = []; this.get = function(i) { // commented because this is very strict and don’t always want to use, sometimes returning undefined is ok //if (! that.data[i]) {throw(’JsonArray - Invalid index passed into Get: ‘ + i);} // purges cached data on an update if (that.clean) { data = []; that.clean = false; } if (! data[i] && that.data[i]) { data[i] = Core.Model.XJson(that.data[i]); } return data[i]; }; return this.get(i); }, /** * Inserts another value into the data structure * * @method push * @param o {array} new row of data * @public */ push: function(o) { if (! o) {throw(’JsonArray - Invalid Object passed into Push’);} this.data.push(o); this.length = this.data.length; }, /** * Updates the object to use the passed data set * * @method update * @param json {array} jsonarray object * @public */ update: function(json) { // validation if (! isType(json, ‘array’)) {throw(’JSONArray - Invalid JSON Array Object passed into Update’);} this.parent.update.call(this, json); this.clean = true; // update public variables this.length = json.length; } }); /** * The XJsonObject class manages … * * @namespace Core.Model * @class XJsonObject * @dependencies library */ Core.Model.XJsonObject = function(scheme, json) { if (! isType(scheme, ‘array’)) {throw(’XJsonObject - Invalid scheme passed into Constructor’);} this.scheme = scheme; this.update(json); }; Core.extend(Core.Model.XJsonObject, Core.Model.Model, { /** * The number of values in the xjson object * * @property length * @type int */ length: 0, /** * The object schema * * @property scheme * @type array */ scheme: [], /** * Updates the object to use the passed data set * * @method update * @param json {object} XJsonObject object * @public */ update: function(json) { // validation if (! isType(json, ‘array’)) {throw(’XJsonObject - Invalid data passed into Update’);} if (json.length !== this.scheme.length) {throw(’XJsonObject - Invalid data (does not match scheme) passed into Update’);} this.parent.update.call(this, json); // private variables var data = this.data, that = this; // update public variables this.length = data.length; Core.batch(this.scheme, function(key, i, json) { var o = json[i], ckey = capitalize(key); data[i] = Core.Model.XJson(o); that[(isType(o, ‘boolean’) && -1 !== key.indexOf(’is’))? key: ‘get’ + ckey] = function() {return data[i];}; that[’set’ + ckey] = function(o) { if ($type(o) !== $type(data[key])) {throw(’XJSONObject - invalid object passed into setter for: ‘ + key);} data[i] = o; }; }, data); } }); /** * The XJsonArray class manages … * * @namespace Core.Model * @class XJsonArray * @dependencies library */ Core.Model.XJsonArray = function(json) { this.update(json); }; Core.extend(Core.Model.XJsonArray, Core.Model.Model, { /** * Boolean used to inform the ‘get’ method to clean the cache * * @property clean * @type boolean */ clean: false, /** * The number of values in the xjson array * * @property length * @type int */ length: 0, /** * The object schema * * @property scheme * @type array */ scheme: [], /** * Execute function ‘fn’ on all elements in collection * * @method batch * @param fn {function} the function to execute * @public */ batch: function(fn) { Core.batch(this.data, function(o, i, scope) { fn(scope.get(i), i); }, this); }, /** * Retrieve the element at ‘i’ from the collection; lazy definition to allow for converting objects on demand * * @method get * @param i {int} index in the data * @public */ get: function(i) { var that = this, data = []; // internally redeclaring to scope the data structure, which will contain already converted objects this.get = function(i) { // commented because this is very strict and don’t always want to use, sometimes returning undefined is ok //if (! that.data[i]) {throw(’XJsonArray - Invalid index passed into Get: ‘ + i);} // purges cached data on an update if (that.clean) { data = []; that.clean = false; } if (! data[i]) { var o = that.data[i]; // if array, then it is an XJsonObject if (isType(o, ‘array’)) { data[i] = new Core.Model.XJsonObject(that.scheme, o); } // otherwise, use generic method else { data[i] = Core.Model.XJson(o); } } return data[i]; }; return this.get(i); }, /** * Inserts another value into the data structure * * @method push * @param o {array} new row of data * @public */ push: function(o) { if (! (isType(o, ‘array’) && o.length === this.scheme.length)) {throw(’XJsonArray - Invalid data passed into Push’);} this.data.push(o); this.length = this.data.length; }, /** * Updates the object to use the passed data set * * @method update * @param json {object} xjsonarray object * @public */ update: function(json) { // validation if (! (json && isType(json, ‘object’) && isType(json.scheme, ‘array’) && isType(json.set, ‘array’))) {throw(’XJsonArray - Invalid data passed into Update’);} this.parent.update.call(this, json.set); this.clean = true; // update public variables this.length = json.length; this.scheme = json.scheme; } }); /** * The XJson class manages … * * @namespace Core.Model * @class XJson * @dependencies library */ Core.Model.XJson = function(o) { if (! o) { return null; } else if (isType(o, ‘array’) && (isType(o[0], ‘array’) || ! o.length)) { return new Core.Model.JsonArray(o); } else if (isType(o, ‘object’) && ! isType(o, ‘array’)) { return (o.scheme)? new Core.Model.XJsonArray(o): new Core.Model.JsonObject(o); } else { return o; } };
This is a lot of code to discuss, which I do not have time for today (Tuesday’s article will have a detailed explanation). I have introduced a String manipulation method ‘capitalize’, which converts strings like ‘mattsnider’ to ‘Mattsnider’. This way all getter and setter methods have the appropriate capitalization. This method is from a small package of string functions, which we will discuss after these JSON objects. For now, let me know your thoughts about these objects and take a look at the test page.
