Last active
December 26, 2015 13:31
-
-
Save mbarkhau/5026379 to your computer and use it in GitHub Desktop.
KSON: Keyless Schemafied Object Notation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* KSON: Keyless Schemafied Object Notation | |
* | |
* Version: 0.1 Alpha | |
* | |
* A serialization format with two goals in mind: | |
* 1. Easily parsable using minimal javascript. | |
* 2. Reduce serialized size compared to JSON. | |
* | |
* 1. is accomplished by using the (comparativly fast) JSON parse/stringify | |
* functions, thus reducing the task of KSON to packing/unpacking the values | |
* according to a predefined schema. This also greatly reduces the size of | |
* the downloaded script, compared with other serialization formats | |
* (gzipped KSON is < 1K). | |
* | |
* 2. is accomplished by eliminating often redundant keys and by extending | |
* native JSON datatypes with an encoding/decoding mechanism. Codecs allow | |
* for a compact serialized data representation. | |
*/ | |
!(function (global) { | |
var DECODERS = {}, ENCODERS = {}, SCHEMAS = {}; | |
function addSchema(schema) { | |
if (typeof schema === 'string') { | |
schema = parse(schema); | |
} | |
SCHEMAS[schema.id] = schema; | |
} | |
function addCodec(name, decoder, encoder){ | |
DECODERS[name] = decoder; | |
ENCODERS[name] = encoder; | |
} | |
function parse(raw, schema_id) { | |
var data = (typeof raw === 'string') ? JSON.parse(raw) : raw, | |
data_length = data.length, | |
is_array, meta_is_subarray, | |
result, tmp_obj, val, | |
decoder, schema, meta_id, | |
i = 0, j, k; | |
if (!schema_id) { | |
schema_id = data[0]; | |
i = 1; | |
} | |
is_array = schema_id[0] === "["; | |
if (is_array) { | |
schema_id = schema_id.slice(2); | |
result = []; | |
} | |
schema = SCHEMAS[schema_id]; | |
var fields = schema.fields, | |
meta = schema.meta, | |
fields_length = fields.length; | |
for (; i < data_length; i += fields_length) { | |
tmp_obj = {}; | |
for (j = 0; j < fields_length; j++) { | |
val = data[i + j]; | |
if (val !== null && val !== undefined) { | |
meta_id = meta[j]; | |
meta_is_subarray = meta_id && meta_id[0] === "["; | |
if (meta_is_subarray) { | |
meta_id = meta_id.slice(2); | |
} | |
decoder = DECODERS[meta_id]; | |
schema = SCHEMAS[meta_id]; | |
if (schema) { | |
val = parse(val, meta[j]); | |
} else if (decoder) { | |
if (meta_is_subarray) { | |
for (k = val.length - 1; k >= 0; k--) { | |
val[k] = decoder(val[k]); | |
} | |
} else { | |
val = decoder(val); | |
} | |
} | |
} | |
tmp_obj[fields[j]] = val; | |
} | |
if (is_array) { | |
result.push(tmp_obj); | |
} else { | |
return tmp_obj; | |
} | |
} | |
return result; | |
} | |
function stringify(data, schema_id, is_subarray) { | |
var is_array = schema_id[0] === "[", | |
schema_id = is_array ? schema_id.slice(2) : schema_id, | |
schema = SCHEMAS[schema_id], | |
fields = schema.fields, | |
fields_length = fields.length, | |
meta = schema.meta, meta_id, meta_is_subarray, | |
i, j, k, obj, val, encoder, | |
result = []; | |
if (!is_subarray) { | |
result[0] = (is_array) ? "[]" + schema_id : schema_id; | |
} | |
if (!is_array) { | |
data = [data]; | |
} | |
var data_length = data.length; | |
for (i = 0; i < data_length; i++) { | |
obj = data[i]; | |
for (j = 0; j < fields_length; j++) { | |
val = obj[fields[j]]; | |
if (val !== null && val !== undefined) { | |
meta_id = meta[j]; | |
meta_is_subarray = meta_id && meta_id[0] === "["; | |
if (meta_is_subarray) { | |
meta_id = meta_id.slice(2); | |
} | |
encoder = ENCODERS[meta_id]; | |
schema = SCHEMAS[meta_id]; | |
if (schema) { | |
val = stringify(val, meta[j], 1); | |
} else if (encoder) { | |
if (meta_is_subarray) { | |
for (k = val.length - 1; k >= 0; k--) { | |
val[k] = encoder(val[k]); | |
} | |
} else { | |
val = encoder(val); | |
} | |
} | |
} | |
result.push(val); | |
} | |
} | |
return (is_subarray) ? result : JSON.stringify(result); | |
} | |
// add the schema schema | |
addSchema({id: 'schema', fields: ['id', 'fields', 'meta'], meta: [0,0,0]}); | |
// equivalent in KSON (if the schema schema were already bootstrapped) | |
// addSchema('["schema", ["id", "fields", "meta"], [0,0,0]]'); | |
// exports | |
return global.KSON = { | |
addCodec: addCodec, | |
addSchema: addSchema, | |
parse: parse, | |
stringify: stringify, | |
encoders: ENCODERS, | |
decoders: DECODERS | |
}; | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment