Showing posts with label json. Show all posts
Showing posts with label json. Show all posts

Tuesday, February 10, 2009

AMF vs. JSON

You can find many blog posts comparing AJAX data transfer formats JSON and XML to AMF3, but they all seem to miss what I see as the 3 biggest advantages to AMF3.

1: AMF3 supports references for objects, strings, and class definitions. If you're encoding an object graph that contains references to the same object over and over, or even the same object type over and over, AMF3 will be significantly smaller over the wire, and once you get the data you won't need to do any manually reconciling of objects that are really the same thing.

2: AMF3 can decode typed objects that have methods, derived properties, and a static class definition. That saves time because you have to do less post-parsing processing of the data. It also makes development a lot quicker, especially if you're using an ORM on the server side. You can send objects retrieved from the database straight over to the client, the user can modify the objects with the GUI, and the objects can be sent straight back to the server to save changes. Your server-side AMF encoder/decoder library and ORM library take can care of all the CRUD grunt work, so all you have to do is figure out a decent data model and how to represent it in the client GUI. I use Python and PyAMF on the server side, which even has support for lazy-loading attributes of objects persisted with the SQLAlchemy ORM.

3: You can implement the IExternalizable interface on any AS3 class to fully customize the object encoding/decoding process. If you're brave and need optimization for large data sets, you can even write and read directly to/from the AMF3 byte stream and use your own custom encoding scheme suited for your data type

Monday, August 25, 2008

Flex JSON-RPC implementation

So, you're checking out Flex and you're thinking to yourself, "Gee this e4x stuff is pretty rad, but it's 2008 and I could really use a good JSON implementation so I can integrate my bitchin' Flex component into my AJAX page." Amazingly, I was thinking the same thing, so I put together a couple of classes to implement a JSON-RPC v1.1 client.

The application code for this post is available on Google code. In addition to the JSON-RPC classes, the application contains a simple gui with controls for testing and logging JSON-RPC communication. To compile the code, you'll also need as3corelib in your compile path, which handles the JSON serialization/deserialization.

The 1st thing you'll need is a JSON-RPC server. If you don't already have one, it shouldn't be too difficult to put together. Follow this tutorial to create a simple Python JSON-RPC server, or use any 1.1 compliant server.

Next, we need to extend mx.rpc.AbstractOperation. This class will send the method invokation to the server and decode the result. Two important methods are overriden. The first is 'send', which will encode the request according to the JSON-RPC v1.1 spec, create a HTTPRequestMessage, and then call the parent invoke() to send the message to the server. If JSON encoding fails, a FaultEvent must be dispatched. Use the parent method dispatchRpcEvent() to make sure the event is dispatched by both the service and the operation.

The other important method is 'processResult', which decodes the response from the server and checks for any errors defined by the server application. The 'processResult' method is in the mx_internal namespace. If you're not familiar with using mx_internal, you should probably read up on it. The parent class takes care of most of the heavy lifting, but you will need to dispatch a FaultEvent if the JSON decode fails, or if a server application error was defined. Set the _result variable equal to the decoded result, and you're good to go.

Finally, we need to extend mx.rpc.AbstractService. This class is used to instantiate mx.rpc.AbstractOperation instances and invoke remote method calls in our application code. The class's main purpose is to act as a proxy that intercepts method calls, so we will be able to invoke a remote method with the syntax: service.method(arguments) instead of operation.send(method, args). You will need to override the 'getOperation' method to instantiate the correct mx.rpc.AbstractOperation subclass.

Here's how the jsonrpc.JsonRpcService can be used in your application code to communicate with the server:

import mx.rpc.events.*;

import jsonrpc.JsonRpcService;

private function callFoo(fooArgs:Object):void
{
// Create service object and
// call remote method 'foo'.
var jsonService:JsonRpcService = new JsonRpcService();
jsonService.rootUrl = 'http://localhost';
jsonService.url = 'test';
jsonService.addEventListener(ResultEvent.RESULT, gotBar);
jsonService.foo(fooArgs);
}

private function gotBar(event:ResultEvent):void
{
event.target.removeEventListener(ResultEvent.RESULT, gotBar);
var bar:Object = ResultEvent.result;
// do something with bar
}