Skip to content

Instantly share code, notes, and snippets.

@DerGoogler
Created October 9, 2022 13:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DerGoogler/85460bc768d6b528f59264d1a50a160f to your computer and use it in GitHub Desktop.
Save DerGoogler/85460bc768d6b528f59264d1a50a160f to your computer and use it in GitHub Desktop.
An JSON prototype parser.
import Mustache from "mustache";
namespace TSON {
export type Vars<T> = {
vars: T;
};
export type Data<T = any, V = any> = Vars<V> & {
[o: string | number | symbol]: T;
};
export type OmitterKeys<T> = keyof T | (keyof T)[];
}
class TSON<T extends TSON.Data<T, V> = any, V extends TSON.Vars<V> = any> {
private _value: string | T;
private _space: number;
public constructor(value: string | T, space?: number) {
this._value = value;
this._space = space || 0;
}
private _interpolate(value: string) {
const vars = (this._value as T).vars;
if (typeof vars === "undefined") return value;
return Mustache.render(value, vars);
}
public get parse(): TSON {
switch (typeof this._value) {
case "object":
this._value = JSON.parse(
this._interpolate(JSON.stringify(this._value))
);
return this;
case "string":
this._value = JSON.parse(this._interpolate(this._value));
return this;
default:
return this;
}
}
public get stringify(): TSON {
switch (typeof this._value) {
case "object":
// return JSON.parse(JSON.stringify(this._value), this._reviver);
this._value = this._interpolate(
JSON.stringify(this._value, null, this._space)
);
return this;
case "string":
this._value = this._interpolate(
JSON.stringify(JSON.parse(this._value))
);
return this;
default:
return this;
}
}
private _handleOmitter(key: TSON.OmitterKeys<T>, value: T | string): T {
switch (typeof key) {
case "object":
let tmp: Record<string, T> = {};
Object.entries(value).forEach(([key_, value], i) => {
if (key.some((elem) => key_ == elem)) {
null;
} else {
tmp[key_] = value;
}
});
return tmp as unknown as T;
case "string":
let { [key]: omitted, ...rest } = value as any;
this._value = rest;
return rest as any;
default:
return {} as any;
}
}
public omit(key: TSON.OmitterKeys<T>): TSON {
switch (typeof this._value) {
case "object":
this._value = this._handleOmitter(key, this._value);
return this;
case "string":
this._value = JSON.stringify(
this._handleOmitter(key, JSON.parse(this._value)),
null,
this._space
);
return this;
default:
this._value = {} as any;
return this;
}
}
public entries(
callbackfn: (key: string, value: any, index: number) => T
): T[] {
return Object.entries(this._value).map<T>(([key, value], index) =>
callbackfn(key, value, index)
);
}
public get(): string | T {
return this._value;
}
}
const content: TSON.Data = {
vars: {
name: {
first: "John",
last: "Olol",
getName: () => {
return "Kevin";
},
},
},
name: "name is {{name.first}}",
work: "{{name.last}} is doctor",
"maritial status": "{{name.getName}} is unmarried",
};
type Content = typeof content;
const val = new TSON<Content>(content, 4);
val.omit("work");
console.log(val.stringify.get());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment