AMF (Action Message Format) is a binary data serialization protocol. Simply put, it transforms objects in memory into a binary string, and can reverse this binary string into an object in memory. It can be used just like JSON, and this library has been build to provide a similar API to that exposed by the JSON functionality in JavaScript.
The purpose of this library is to provide a consistent and symmetric implementation of the AMF specification in both PHP & JavaScript.
Well, it's up to you. JSON is perfectly suited to the web, however it does have some shortcomings which are addressed by AMF. For starters, JSON cannot handle complex object graphs with circular references; additionally, it cannot serialize dates & byte arrays - you would need to do some additional work to support these in JSON (convert date to unix timestamp, byte arrays to base64).
Hells no. JSON is great; AMF can simply provide you with some additional functionality which could help you build your web app.
To begin using this library, you will need to install it via Composer:
bower install -S infomaniac-amf.js#latest
This will download the repository for you and make the library available for inclusion. For convenience, a file dist/amf.js has been compiled for you with all of its dependencies, uglified and browserified. The file is a mere 43kb.
<script src="bower_components/infomaniac-amf.js/dist/amf.js" type="text/javascript"></script>Here is a simple example of encoding an object to AMF:
var data = {
any: 'data',
you: 'like!'
};
var encodedData = AMF.stringify(data);
console.log(encodedData);This will produce a binary string which represents your given data.
If you were to inspect the HTTP traffic of a page that produces AMF data, using a tool such as Charles Proxy, you would see the following output:
To decode this string, simply do the following:
var data = {
any: 'data',
you: 'like!'
};
var encodedData = AMF.stringify(data);
console.log(AMF.parse(encodedData));If you were to console.log this data, it would look identical to the input data given to the AMF.stringify function.
Object {any: "data", you: "like!"} AMF allows you to encode an object and retain some metadata about it; for example, when serializing an instance of a class (not Object) the library will retain the class' fully qualified namespace name and use it to reconstruct an object of that type upon decoding.
Consider the following class:
var Person = function() {
this.name = 'Bob';
this._classMapping = 'Person';
};If we encode an instance of this object, by default its class type will be ignored and when the data is decoded, the resulting value will be a plain PHP Object instance.
var Person = function() {
this._classMapping = 'Person';
};
var data = new Person();
data.name = "Bob";
var encodedData = AMF.stringify(data);
console.log(AMF.parse(encodedData));...will produce...
Object {name: "Bob"}In order to retain the class type in AMF, you will need to add the following:
- an additional flag to the
AMF.stringifyfunction call - define a
_classMappingvariable on the object(s) being encododed, and - register a "class alias" using
AMF.registerClassAliasto associate the_classMappingvalue to its related class type
var Person = function() {
this._classMapping = 'Person';
};
var data = new Person();
data.name = "Bob";
var encodedData = AMF.stringify(data, AMF.CLASS_MAPPING);
AMF.registerClassAlias('Person', Person);
console.log(AMF.parse(encodedData));Now, when this data is decoded, the library will attempt to create a new instance of the Person class and set its public property name to "Bob".
Person {_classMapping: "Person", name: "Bob"} The AMF spec allows for the serialization of several different data-types.
Here is a link to the latest specification: AMF3 Spec - January 2013
This library implements 10 of the 18 data-types described in the specification. The reason for the support of only a subset of these types can be seen in two lights: utility and limitation. Here is an exhaustive list of the data-types available:
| Data-Type | Included | Reason for exclusion |
|---|---|---|
| Undefined | ✔ | - |
| Null | ✔ | - |
| False | ✔ | - |
| True | ✔ | - |
| Integer | ✔ | - |
| Double | ✔ | - |
| String | ✔ | - |
| XML Document | ✗ | Who needs XML? |
| Date | ✔ | - |
| Array | ✔ | - |
| Object | ✔ | - |
| XML | ✗ | Who needs XML? |
| ByteArray | ✔ | - |
| Vector | ✗ | Not high priority - also, possible browser incompat issue with JS |
| Vector | ✗ | Not high priority - also, possible browser incompat issue with JS |
| Vector | ✗ | Not high priority - also, possible browser incompat issue with JS |
| Vector | ✗ | Not high priority - also, possible browser incompat issue with JS |
| Dictionary | ✗ | PHP cannot use objects are array keys |
This project is licensed under the MIT license.
While writing this library, I used several libraries to validate my progress, and to help me come unstuck. I would like to extend a special thanks to the following libraries and individuals:
- SabreAMF
- AmfPhp
- Charles Proxy's wonderful AMF implementation
- Arseny Vakhrushev (neoxic) for his patience, guidance, advice and help
- Robert Cesaric, Grant McMullin and Andre Venter for their insight and advice
- My esteemed colleagues at Zando
