A compact, URL-friendly serialization format that is smaller than JSON while remaining human-readable and fast to parse.
RJSON (Remote JavaScript Object Notation) is a specification and implementation inspired by RISON and it was originally designed for better frontend-to-backend communication via search parameters.
JSON is an excellent interchange format, but:
- It is not as compressed as it can be
- It is not url friendly
- It cannot represent several JavaScript runtime values:
undefinedNaNInfinity-Infinity-0
RJSON preserves these values while remaining compact, human-readable, and URL-friendly.
const value = {
active: true,
deletedAt: undefined,
score: NaN,
"limit.upper": Infinity,
"limit.lower": -Infinity,
};
const text = RJSON.stringify(value);Output:
(active:T,deletedAt:U,score:X,limit.upper:I,limit.lower:-I)- β‘ Fast parser with direct character scanning (recursive descent parsing).
- π¦ Smaller than JSON for many real-world payloads
- π URL-friendly syntax
- π§© Supports objects, arrays, strings, numbers, booleans
- π Supports
null,undefined,-0,NaN,Infinity,-Infinity - ποΈ Built-in mapped-array compression
~T(id,title,body)~->{ id:true, title:true, body:true } - π Value-preserving roundtrip.
RJSON.parse(RJSON.stringify(value))preserves JavaScript value semantics. - π Tagged template support
- βοΈ Whitespace support (starting from v2.1.11)
- π Runtime agnostic (Node.js, Bun, Deno, Browser)
- π¦ TypeScript ready
- π§ Zero dependencies
- π― Why RJSON?
- β¨ Features
- π Get Started
- π¦ Quick Start
- π Syntax Overview
- π Core Types
- ποΈ Mapped Arrays
- π§ API Reference
- π License
- ποΈ Thanks and Enjoy
- π Be a Sponsor
bun add @bepalo/rjsonnpm install @bepalo/rjsonpnpm add @bepalo/rjsonimport { RJSON } from "jsr:@bepalo/rjson";import { RJSON } from "@bepalo/rjson";
const user = RJSON.parse(
"(name:'Natnael',age:28,active:T,tasks:_('push','deploy','sleep')_)",
);
console.log(user);Output:
{
name: "Natnael",
age: 28,
active: true,
tasks: [ "push", "deploy", "sleep" ],
}import { RJSON } from "@bepalo/rjson";
const text = RJSON.stringify({
name: "Natnael",
age: 28,
active: true,
});
console.log(text);Output:
(name:'Natnael',age:28,active:T)import { RJSON } from "@bepalo/rjson";
const text = RJSON.stringify([1, 3.1415, null, undefined, true, "hello"]);
console.log(text);Output:
_(1,3.1415,N,,T,'hello')_import { RJSON } from "@bepalo/rjson";
const text = RJSON.stringifyMappedArray(true, ["id", "title", "body"]);
console.log(text);Output:
~T(id,title,body)~import { rjson } from "@bepalo/rjson";
const name = "Natnael";
const age = 28;
const user = rjson`(name:'${name}',age:${age},active:T)`;
console.log(user);Output:
{
name: "Natnael",
age: 28,
active: true,
}| Type | RJSON | JSON |
|---|---|---|
| Object | (name:'John') |
{"name":"John"} |
| Array | _(1,2,3)_ |
[1,2,3] |
| Mapped Array | ~T(admin,user)~ |
{"admin":true,"user":true} |
| String | 'hello' "hello" `hello` |
"hello" |
| Number | 123 |
123 |
| Boolean | T / F |
true / false |
| Null | N |
null |
| Undefined | U |
Not supported |
| NaN | X |
Not Supported |
| Infinity | I |
Not Supported |
| -Infinity | -I |
Not Supported |
| -0 | -0 |
Not Supported |
(name:'John',age:30)Produces:
{
name: "John",
age: 30
}_(1,2,3,4)_Produces:
[1, 2, 3, 4];(user:(name:'John',age:30),active:T)Produces:
{
user: {
name: "John",
age: 30
},
active: true
}RJSON supports three string delimiters: ' " `
'hello'
"hello"
`hello`The serializer automatically chooses the delimiter that requires the least escaping.
RJSON.stringify(`'"hello"'`);Output:
`'"hello"'`This keeps serialized output compact and readable.
Supported formats:
123
-123
+123
12.5
1e10
1e-10
-0
X -> NaN
I -> Infinity
-I -> -InfinityExamples:
age:28
price:19.99
distance:1.5e6_( T, F )_Produces:
[true, false];NProduces:
null;(name:U)Produces:
{
name: undefined;
}Empty values are also treated as undefined:
(name:,array:_(,)_,mapped:~(a)~,empty:(),end:)Produces:
{
name: undefined,
array: [ undefined ],
mapped: {
a: undefined,
},
empty: {},
end: undefined,
}Mapped arrays compress repeated values.
Instead of doing:
{
admin: true,
editor: true,
user: true
}Use:
~T(admin,editor,user)~Produces:
{
admin: true,
editor: true,
user: true
}The value can be any valid RJSON type. However, to have an object as value
its start token ( has to be escaped.
NOTE: Allowed whitespace positions. Also whitespaces are not required.
~ \(roles:_('admin','user')_) (create,update,delete)~
~ F (create,update,delete)~
~ ~ F (admin,user)~ (create,update,delete)~Parses RJSON from string.
const value = parseRJSON("(name:'John',active:T)");Serializes JavaScript values to RJSON format.
const text = stringifyRJSON({
name: "John",
active: true,
});Result:
(name:'John',active:T)Creates mapped-array expressions.
stringifyRJSONMappedArray(true, ["read", "write", "delete"]);Result:
~T(read,write,delete)~Tagged-template parser.
const data = rjson`
(name:'John')
`;RJSON v2.x introduces a fully optimized grammar layout that treats explicit null and implicit undefined as independent, native values. If you are migrating an existing application from a v1.x runtime, use the matrix below to audit changes to your network transport footprints and api surface.
| Value / API Reference | Target v1.0.10 | Target v2.1.11 | Notes / Semantic Shifts |
|---|---|---|---|
null |
"" |
"N" |
Now serialized explicitly to prevent collision with missing properties. |
undefined |
"U" |
"" | "U" |
Evaluates to an empty slot inside collection layouts; returns "U" if standalone. |
[1, undefined, 3] |
_(1,U,3)_ |
_(1,,3)_ |
Array holes leverage highly efficient conditional trailing comma notation. |
[,] [,,] |
_()_ _(,)_ |
_(,)_ _(,,)_ |
Empty array elements are now handled properly and treated as undefined. |
NaN |
null |
X |
Native support added for IEEE 754 special values. |
Infinity |
null |
I |
Native positive infinity tracking. |
-Infinity |
null |
-I |
Native negative infinity tracking. |
-0 |
0 |
-0 |
Sign-bit fidelity preserved during serialization loops. |
stringifyRJSONString |
stringifyRJSONString |
stringifyRJSONText |
Utility renamed to clear naming collision with global String. |
RJSON.stringifyString |
RJSON.stringifyString |
RJSON.stringifyText |
Namespace reference updated to point to the text subsystem encoder. |
MIT
If you find RJSON useful, please consider starring the repository and sharing it with others.
Support development and future improvements.
