Skip to content
David Nolen edited this page Aug 8, 2014 · 38 revisions

Reading

In order to read Transit encoded JSON you need to construct a reader:

var reader = transit.reader("json");

Currently "json" is the only type of reader available. The above will construct a reader instance which has only one method, read:

var anArray = reader.read("[1,2,3]");

In Transit the map encoding returns ES6-like Maps not JavaScript objects. The primary difference with ES6 Maps is that lookup is based on value not reference:

var aMap = reader.read('{"foo":"bar"}');
aMap.get("foo");

Writing

Like reading, writing is fairly straightforward. Constructing a writer looks very much like constructing a reader:

var writer = transit.writer("json");

Writers only have a single method, write:

writer.write([1,2,3]);

This will return a '[1,2,3]' as expected.

Compare to writing map-like values:

writer.write({foo:"bar"});

This will return '["^ ","foo","bar"]'. Maps get written out as arrays as this form is more efficient for decoding. For debugging purposes it's useful to construct a verbose writer:

var vwriter = transit.writer("json-verbose");

And now the result of writing map-like values is easier to read:

vwriter.write({foo:"bar"});

This will return '{"foo":"bar"}'.

Writing Custom Values

Being able to easily write out graphs of JavaScript objects is one the big benefits of Transit. Transit will recursively encode and ground values need no special treatment.

To demonstrate this lets define some simple geometry primitives:

var Rect = function(origin, size) {
  this.origin = origin;
  this.size = size;
};

var Point = function(x, y) {
  this.x = x;
  this.y = y;
};

var Size = function(width, height) {
  this.width = width;
  this.height = height;
};

var aRect = new Rect(new Point(0, 0), new Size(150,150));

In order to write out aRect we need write handlers for all of the types involved. First let's write a handler for Point:

var PointHandler = transit.makeWriteHandler({
  tag: function(v, h) { return "point" },
  rep: function(v, h) { return [v.x, v.y]; },
  stringRep: function(v, h) { return null; }
});

Write handlers are constructed with transit.makeWriteHandler. Custom types always become tagged values on the wire and the handler methods specify how your instance will become a proper Transit tagged value. Write handlers must supply at least three methods: tag, rep, and stringRep. Each handler method recieve the instance v as the first argument, and the handle h as the second argument.

tag should be a function that will take the instance and return a string based tag. You can of course use the instance argument v to write out different tags if you like but we're going to keep it simple here.

rep is the representation to use for the tagged value. In this case we simply return an array containing the x and y properties. These properties are numbers, a ground type, so there's nothing more for us to do.

stringRep is for tagged types that have sensible representation as JSON object keys which must be strings. For the most part you can omit this method but we've left it here for completeness.

We can now write points, for example with a verbose writer:

vwriter.write(new Point(1.5,2.5));

This will return '{"~#point:[1.5,2.5]"}'.

Let's write the handlers for Size and Rect:

var SizeHandler = transit.makeWriteHandler({
  tag: function(v, h) { return "size"; },
  rep: function(v, h) { return [v.width, v.height]; },
  stringRep: function(v, h) { return null; }
});

var RectHandler = transit.makeWriteHandler({
  tag: function(v, h) { return "rect"; },
  rep: function(v, h) { return [v.origin, v.size]; },
  stringRep: function(v, h) { return null; }
});

That's it we can now write out Rect instances!

vwriter.write(aRect);

This will return '{"~#rect":[{"~#point":[0,0]},{"~#size":[150,150]}]}'. As we said earlier transit-js will recurse through the value returned by the rep methods and encode as needed.

Clone this wiki locally