FOA - Fast Object and Array encoding/decoding - Specification

This page is the official specification of the FOA encoding/decoding method.

Version:

The current version of the FOA specification is 1.0 and is owned by Anders Lövgren.

Contact:

If you have questions/suggestions or like to get involved in the development of the FOA specification, please send me an email at either anders.lovgren@bmc.uu.se or lespaul@algonet.se

Introduction:

FOA is an encoding/decoding method specifically designed to be an efficient method for exchanging data between applications and/or networked hosts.

It can be used for passing data between RESTful web services, for implementing object oriented network protocol (the client/server messages are objects) or as an generic object serializer to storage (i.e. write objects to disk in C/C++ and read them back in Java).

Other applications of FOA is possible, these ones are just some typical uses. FOA can be seen as an cousine to JSON, but with some characteristics that makes it unique.

Specification:

FOA is line oriented:

FOA is line oriented. An encoded line consist of either an special char (one of '([])') or data (could be i.e. the value of an object member, an array value or any text).

It should be exactly one special char or data item per encoded line allways followed by an newline character.

Encoding objects:

An object is encoded by placing its members within '(' and ')'. These two characters denotes the start and end of an encoded object. The object can be given an name by using 'name = ('.

Encoding arrays:

An array is encoded by placing its values within '[' and ']'. These two characters denotes the start and end of an encoded array. The array can be given an name by using 'name = ['.

Encoding values:

Values are usually lines of data within an object or array, but it's also possible to pass data outside of any special char enclosing scope. As with objects and arrays, values can be given a name using 'name = value'. This is useful for mapping values to a object member or when encoding an hash array.

Escape special chars:

One question that comes up is: How to handle values containing the assignment character '=' or a special char?

The answer is that these five characters should be escaped using the HTTP URI encoding method. Meaning they are replaced by '%NN', where NN is the ASCII value of the special char.

Implementing escape:

An implementation of this specification should opt in for clients to disable escaping, because its potential slow and might not be needed. This is true when both side of the data exchange knows it not going to be needed. Whether to enable/disable escaping should be possible to control at runtime to allow dynamic control of escaping.

Dynamic control escaping:

If the peer knows in advance that the data it will send needs escaping, then it can pass an escape control message to the remote side telling it to turn on escaping when decoding the data.

One method for dynamic control of escaping could be to agree on having special messages like '@escape = [true|false]' telling the other side to enable/disable escaping. Control messages like this should not be part of the FOA implementation, its left to applications to implement using FOA as a tool.

Syntax check:

An implementation of FOA is not expected to perform anything more than single line syntax check. It could consist of checking that a string used to name a value don't contain an '=' or one of the special chars.

Lexical analysis:

Lexical analysis should (if at all) be implemented as an optional layer on top of the core implementation of FOA.

Formal syntax:

The formal syntax uses an description language that can be found in many RFC documents.

line := (name '=' data | data) + '\n'
data := text | spec
name := text - '='
text := ascii - (spec | '=')
spec := '([])'

Note that ascii means all characters that matches the C library function isascii(). Thus, text is any ASCII except for '=' and any special char.

Sending files:

One major problem using XML with web services is how to send files. This section gives four example on how FOA handles it.

Text files:

This could be done by sending each line in the file as an array value: 'file = [ ... ]', where '...' represents the file content.

Binary files:

Encode the file content using base64 or similar and send it as a text file.

Control object:

Use an special control object to denote the start of an file:

@file = (
name = xxx
size = yyy
)

Upon receiving the object named @file, the receiver is expected to read yyy bytes of data (possibly) storing it using the suggested name.

This approach solves the problem of sending any kind of file, and as a bonus it could be used to pass additional meta information like file permissions and owner.

Message response:

If the client/server implements an request/response protocol closing the socket between each request, then theres no need to encode the file at all. Just send it and close the pipe, this is typical how HTTP 1.0 works.

Reference implementations:

The C library libfoa is considered the official reference implementation. It is published at SourceForge.