JsonObject Model Prototype

I have been doing a lot of server-side work in PHP and JAVA this past month. One of the design practices used by server-side webapp languages is the MVC (model-view-controller) framework. An MVC makes writing extensible and scalable code, much easier. In JavaScript I have seen a couple of attempts at a similar MVC framework, but most of the time it is overkill or poorly implemented. Shutterfly.com on the other-hand, has a lot of JavaScript and a fairly solid MVC implementation.

I have been toying with JavaScript MVC concepts all week and want to share what I developed to improve working with JSON objects. Keep in mind this is a work in progress and I am open to any suggestions:

Example 1: Sample Code

/**
 * The JsonObject class manages …
 *
 * @namespace Core.Model
 * @class JsonObject
 * @dependencies core
 */

Core.Model.JsonObject = function(data) {
	this.update(data);
};

Core.Model.JsonObject.prototype = {
	JKEYS: [],

	MODEL: JsonObject,
	
	update: function(data) {
		var obj = {},
			that = this,
			i = 0;

		// iterate through the JSON object keys
		for (var key in data) {
			var o = data[key];
			
			if (! isType(o, function)) {
				// this key is not in the model
				if (-1 < that.JKEYS.indexOf(key)) {
					throw(Invalid key ( + key + ) passed into  + that.MODEL);
				}
				
				obj[key] = o;

				that[isType(o, boolean)? key: get + ckey] = function() {return obj[key];};
				that[set + ckey] = function(o) {return obj[key] = o;};
				i += 1;
			}
		};

		// the keys in the object do not match the keys in the model
		if (i != JKEYS.length) {
			throw(Invalid number of keys passed into  + that.MODEL);
		}
	}
});

This method takes a JSON object and applies getter/setter methods to that object. Each time update is called, it validates against JSKEYS, which should be an array of the expected keys. We also remove any functions that might have been attached to the data object. You may also note that I have a special check for boolean values that does not attach the get preface to the getter method. This is because I always preface boolean values with is or has (or something like that), and I want that preserved in the Function attached to the JsonObject.

Here is an example of how you might use it:

Example 2: Using JsonObject

// a JSON object, most likely returned from the server, representing a car
var carJson = {
	make: ford,
	model: contour,
	year: 1996,
	price: $2,000,
	isNew: false
};

// use the extend (Object Extension) method to create a CarObject, with the appropriate JKEYS set
Core.extend(Core.Model.CarObject, Core.Model.JsonObject, {
	JKEYS: [make, model, year , price],
	MODEL: CarObject
});

var car = new Core.Model.CarObject(carJson);

Example 2 will create a CarObject (extended JsonObject), with the following members:

Example 3: CarObject Structure

CarObject = {
	// constants defined by the prototype object
	JKEYS: [make, model, year , price],
	MODEL: CarObject,
	
	getMake(),
	setMake(),
	
	getModel(),
	setModel(),
	
	getYear(),
	setYear(),
	
	getPrice(),
	setPrice(),
	
	isNew(),
	setIsNew()
}

I find it much easier to work with the JsonObjects once the getters and setters have been created, because you have defined what should be there. Plus, with the validation you can be sure that you received the correct JSON Object. Some possible improvements would be to support nested JsonObjects and JsonArrays, and setter type validation (although, this might be overkill).

There are really only 3 types of models that you might need to use in JavaScript: JSON Objects/Arrays, Query strings, and XML. Creating the Models is a good first step in building an MVC as you will need to pass these between the controller and the view, to update the view and send messages to the server. Next week, I will look into these other model types and improve this one a bit.