Portable Object Notation

Portable Object Notation (PON) is a lightweight data-interchange format that builds on the base of the JavaScript Object Notation (JSON) industry standard data-interchange format. A flaw of JSON is that its stream coding is inefficient for certain patterns of data, most notably binary data. PON extends JSON to increase usability and readability while reducing the space cost of coding binary data, and without adding complexity. A standard JSON stream of bytes is a valid PON stream, but a valid PON stream may or may not be a valid JSON stream, depending on whether or not the extended features of PON are used. There is one limitation of PON when compared with JSON - the outermost container for PON data must be an object; unlike JSON, it cannot be a singleton value or an array. That is, the first non-whitespace character of a PON stream is the { character.

Just like JSON, PON is built on two data structures:

  • A collection of name/value pairs - an object
  • An ordered list of values - an array

The features of PON are a superset of JSON. Here are the added features:

  1. Keywords in an object do not need to be enclosed in quotation marks if the first character of the keyword is alphabetic (a-z and A-Z) and the rest of the characters are alphabetic, digits, periods, dollar signs and underscores.
  2. A new concept exists that is a standalone keyword that does not contain a value. Thus, the JSON syntax
           : value
    that follows a JSON keyword is optional in PON.
  3. Keywords with or without values are positional within a PON object. That is, they may be inserted and accessed by index as well as by keyword value. Conversions between tree structures in program memory and the byte stream format maintain the keyword ordering.
  4. A new binary data type is allowed as a value. The syntax is:
           ( digits ) binary-data
    The value digits is one or more decimal digits that is the number of bytes that follow the closing parenthesis. Zero is allowed. Whitespace inside the parentheses or before the binary-data is not allowed. The value binary-data is simply a stream of unencoded bytes, the number of which is specified by digits.
object
{}
{ members }
members
item
item , members
item
keyword
keyword : value
keyword
string
keyword-chars
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null
(digits)bytes

string
""
" chars "
chars
char
char chars
char
any Unicode character
    except " or \ or
    control character
\"
\\
\/
\b
\f
\n
\r
\t
\u four-hex-digits
number
int
int frac
int exp
int frac exp
int
digits
- digits
frac
. digits
exp
e digits
digits
digit
digit digits
e
e
e+
e-
E
E+
E-
keyword-chars
one or more chars from
a-z, A-Z, digits, ., $ and _,
starting with
a-z or A-Z

bytes
zero or more raw bytes