Skip to content

Instantly share code, notes, and snippets.

@crabmusket
Last active Oct 1, 2019
Embed
What would you like to do?
JSON utilities for Deno

json.ts

badge: stability is WIP

Includes a type definition and some utility functions for working with arbitrary JSON data in Deno. If you don't know the shape of some data, but you're sure that it will be JSON data (e.g. no functions, undefined, NaN or Infinity), this type is safer than using any.

Usage example:

import { JsonValue, isJsonValue, parseJson } from "https://gist.githubusercontent.com/crabmusket/660f58266d91c316db35bbcbeed221cb/raw/020eb47ad479c56cbd01c3de009d65f6a2c184b9/json.ts";

console.log(isJsonValue({foo: "bar"})); // true
console.log(isJsonValue(5)); // true
console.log(isJsonValue(new Number(5))); // false, not a POJSO

let result: JsonValue | Error = parseJson("blahblah"); // typesafe parse, in this case will be Error
/** For the spec of the JSON type, see http://json.org */
export type JsonValue = JsonObject | JsonArray | number | string | boolean | null;
/** JSON objects can have any string key. */
export interface JsonObject {[key: string]: JsonValue};
/** For the explanation of this type, see https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 */
export interface JsonArray extends Array<JsonValue> {};
/** Narrow the type of a JsonValue to check if it's an object. */
export function isJsonObject(value: JsonValue): value is JsonObject {
return typeof value === 'object' && value !== null && !isJsonArray(value);
}
/** Narrow the type of a JsonValue to check if it's an array. */
export function isJsonArray(value: JsonValue): value is JsonArray {
return Array.isArray(value);
}
/** Checks at runtime whether the value you've passed is actually a POJSO. */
export function isJsonValue(value: any): value is JsonValue {
if (typeof value === 'string' || typeof value === 'boolean' || value === null) {
return true;
}
if (typeof value === 'number') {
return isFinite(value) && !isNaN(value);
}
if (Array.isArray(value)) {
return value.every(isJsonValue);
}
if (typeof value === 'object') {
if (value.__proto__.constructor !== Object) {
return false;
}
for (let key in value) {
if (!isJsonValue(value[key])) {
return false;
}
}
return true;
}
return false;
}
/** Safe JSON parser which returns an Error instead of throwing it. */
export function parseJson(input: string): JsonValue | Error {
try {
return JSON.parse(input) as JsonValue;
} catch (e) {
return e as Error;
}
}
/** JSON parser which asserts that the result is of the JsonValue type. Throws on invalid input. */
export function parseJsonOrThrow(input: string): JsonValue {
return JSON.parse(input) as JsonValue;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment