Parse and edit JSONC in JavaScript.
This is especially useful for making programmatic changes to JSON config files.
Deno:
deno add jsr:@david/jsonc-morph
Or with npm:
npm install jsonc-morph
import { parse, parseToValue } from "@david/jsonc-morph";
// parse directly to a plain JavaScript value
const config = parseToValue(`{
// database settings
"host": "localhost",
"port": 5432
}`);
console.log(config.host); // "localhost"
console.log(config.port); // 5432
// parse to a CST for programmatic editing
const root = parse(`{
// 1
"data" /* 2 */: 123 // 3
} // 4`);
// get the root object
const rootObj = root.asObjectOrThrow();
// set its "data" property to have a new value
rootObj.getOrThrow("data").setValue({
"nested": true,
});
// append a new key
rootObj.append("new_key", [456, 789, false]);
// inspect the output
assertEquals(
root.toString(),
`{
// 1
"data" /* 2 */: {
"nested": true
}, // 3
"new_key": [456, 789, false]
} // 4`,
);By default, parse and parseToValue allow more than just JSONC (comments,
trailing commas, single-quoted strings, hexadecimal numbers, etc.). You can
customize this behaviour by passing options:
import { parse, parseToValue } from "@david/jsonc-morph";
// disable specific extensions
const root = parse(text, {
allowComments: false, // reject // and /* */ comments
allowTrailingCommas: false, // reject trailing commas in arrays/objects
allowSingleQuotedStrings: false, // reject 'single quoted' strings
allowHexadecimalNumbers: false, // reject 0xFF style numbers
allowUnaryPlusNumbers: false, // reject +42 style numbers
allowMissingCommas: false, // reject missing commas between elements
allowLooseObjectPropertyNames: false, // reject unquoted property names
});
// parseToValue accepts the same options
const value = parseToValue(text, { allowComments: false });For strict JSON parsing (only allow JSON), use parseStrict or
parseToValueStrict:
import { parseStrict, parseToValueStrict } from "@david/jsonc-morph";
// all extensions disabled by default
const root = parseStrict('{"name": "test"}');
// selectively enable specific extensions
const rootWithComments = parseStrict(text, { allowComments: true });
// same for `parseToValueStrict`
const value = parseToValueStrict('{"name": "test"}');