Skip to content

ason-lab/ason-js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ason-js

License: MIT npm

Zero-dependency JavaScript/TypeScript library for ASON (Array-Schema Object Notation) — a token-efficient, schema-driven data format for LLM interactions and large-scale data transfer.

ason-js is the official runtime for both JavaScript and TypeScript users. It ships ESM/CJS builds and bundled .d.ts type declarations in a single package, so there is no separate ason-ts package to install.

Works in browsers, Node.js, Deno, Bun and any JS framework: Vue, React, Svelte, SolidJS, etc.

中文文档


What is ASON?

ASON separates schema from data, eliminating repeated key names found in JSON. The schema is declared once; each data row carries only values:

JSON (100 tokens):
{"users":[{"id":1,"name":"Alice","active":true},{"id":2,"name":"Bob","active":false}]}

ASON (~35 tokens, 65% saved):
[{id:int, name:str, active:bool}]:(1,Alice,true),(2,Bob,false)
Aspect JSON ASON
Token efficiency 100% 30–70% ✓
Key repetition Every object Declared once ✓
Human readable Yes Yes ✓
Type annotations None Built-in ✓
Data size 100% 40–55%

Install

npm install ason-js

Or copy dist/ason.min.js directly into a web page (exposes a global ASON object).

TypeScript users do not need a separate stub package. npm run build emits dist/index.d.ts, and the package exports it via the types field.


Quick start

import { encode, encodeTyped, encodePretty, encodePrettyTyped,
         decode, encodeBinary, decodeBinary } from 'ason-js';

const users = [
  { id: 1, name: 'Alice', score: 9.5 },
  { id: 2, name: 'Bob',   score: 7.2 },
];

// Schema is inferred automatically — no schema string needed
const text        = encode(users);           // untyped schema
const textTyped   = encodeTyped(users);      // typed  schema (use for typed round-trip)
const pretty      = encodePretty(users);     // pretty + untyped
const prettyTyped = encodePrettyTyped(users);// pretty + typed
const blob        = encodeBinary(users);     // binary (schema inferred internally)

console.log(decode(textTyped));              // original array restored
console.log(decode(prettyTyped));            // same from pretty
console.log(decodeBinary(blob, '[{id:int, name:str, score:float}]')); // binary decode

Note on encode vs encodeTyped encode(obj) emits an untyped schema ({id,name}) so the output is shorter. When decoded, all values without explicit types are returned as strings. Use encodeTyped(obj) when you need the round-trip to preserve numeric and boolean types.


API

Type inference rules

JS value Inferred ASON type
integer number int
fractional number float
boolean bool
string str
null / undefined str? (optional)

Note: Schema is inferred from the first element of an array. To make a field optional (str?), ensure the first element has null for that field.

encode(obj) → string

Serialize a plain object or array to ASON text with an inferred untyped schema. All values are written without type annotations. When decoded, all fields come back as strings:

encode({ id: 1, name: 'Alice' });
// → '{id,name}:\n(1,Alice)\n'

encode([{ id: 1 }, { id: 2 }]);
// → '[{id}]:\n(1),\n(2)\n'

decode(encode({ id: 1, name: 'Alice' }));
// → { id: '1', name: 'Alice' }  ← all strings when schema is untyped

Use encodeTyped when you need decode to restore the original types.

encodeTyped(obj) → string

Same as encode but emits an inferred typed schema. Use this when you want decode() to restore the original types:

encodeTyped({ id: 1, name: 'Alice', active: true });
// → '{id:int,name:str,active:bool}:\n(1,Alice,true)\n'

encodePretty(obj) → string

Pretty-printed ASON text with inferred untyped schema.

encodePrettyTyped(obj) → string

Pretty-printed ASON text with inferred typed schema.

decode(text) → object | object[]

Deserialize ASON text. The schema is embedded in the text itself:

const rec  = decode('{id:int, name:str}:\n(1,Alice)\n');
const rows = decode('[{id:int, name:str}]:\n(1,Alice),\n(2,Bob)\n');

encodeBinary(obj) → Uint8Array

Serialize to binary format. Schema is inferred internally — no schema string needed:

const data = encodeBinary(rows);

decodeBinary(data, schema) → object | object[]

Deserialize from binary format. Schema is required because the binary wire format carries no embedded type information:

const rows = decodeBinary(data, '[{id:int, name:str}]');

Supported types

Schema type JS value Example
int number (integer) 42, -100
uint number (non-negative integer) 0, 9007199254740991
float number 3.14, -0.5
bool boolean true, false
str string Alice, "Carol Smith"
T? value or null hello / null

Optional fields: append ? to any type (str?, int?, float?, bool?, uint?).


Browser (CDN) usage

<script src="dist/ason.min.js"></script>
<script>
  const text = ASON.encodeTyped([{id:1, name:'Alice'}]);
  console.log(ASON.decode(text));
</script>

ESM in browser

<script type="module">
  import { encodeTyped, decode } from './dist/index.js';
  const text = encodeTyped([{id:1, name:'Alice'}]);
  console.log(decode(text));
</script>

Vue / React / Svelte / SolidJS

Works as a regular npm package — just import and use:

// Vue composable example
import { encodeTyped, decode } from 'ason-js';

export function useAson() {
  const serialize   = (data: object[]) => encodeTyped(data);
  const deserialize = (text: string)   => decode(text);
  return { serialize, deserialize };
}

Binary format

Little-endian layout, byte-identical to ason-rs and ason-go:

Type Bytes
int 8 (i64 LE)
uint 8 (u64 LE)
float 8 (f64 LE)
bool 1
str 4-byte length LE + UTF-8 bytes
optional 1-byte tag (0=null, 1=present) + value
slice 4-byte count LE + elements

Build from source

npm install
npm run build    # generates dist/index.js, dist/index.cjs, dist/index.d.ts, dist/ason.min.js
npm test         # vitest, 46 tests

Run examples

node examples/basic.js     # 9 scenarios, basic usage
node examples/complex.js   # 20 scenarios, edge cases
node examples/bench.js     # performance vs JSON.parse / JSON.stringify

Performance

ASON JS produces 50–55% smaller output than JSON. Because JSON.parse / JSON.stringify are implemented in C, raw speed is slower — but:

  • Network bandwidth is typically the bottleneck — 50% smaller payload saves more time than parse overhead costs
  • LLM token cost — 30–70% fewer tokens = lower API cost and faster responses
  • Binary formatencodeBinary / decodeBinary is fastest for machine-to-machine transfer

For latency-sensitive hot paths, use the Rust or Go implementations if your stack supports them.


License

MIT

Contributors

Latest Benchmarks

Measured on this machine with Node 24.14.0.

Headline numbers:

  • Flat 1,000-record dataset: ASON text 58,539 B vs JSON 121,451 B (51.8% smaller)
  • Flat 5,000-record dataset: ASON serialize 8.93ms vs JSON 13.27ms, but deserialize 20.10ms vs JSON 16.92ms
  • Large 10,000-record dataset: ASON serialize 37.86ms vs JSON 20.23ms, deserialize 37.25ms vs JSON 33.82ms
  • Throughput summary on 10,000-record-style text path: ASON text serialize ran at 0.30 M records/s vs JSON 0.75 M-class baseline, and deserialize was roughly at parity in this run
  • Binary path is mainly useful for decode and transport size here: on 1,000 records, BIN deserialize 4.68ms vs JSON 2.08ms, with payload 72,784 B vs JSON 121,451 B

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors