A web-based tool to view, edit, format, and validate JSON with multiple editing modes including tree, code, text, and preview
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive configuration system with over 40 options for customizing editor behavior, appearance, and functionality through the JSONEditorOptions interface.
Basic editor configuration options that control fundamental behavior.
interface CoreOptions {
/** Editor mode: tree, view, form, code, text, or preview */
mode?: "tree" | "view" | "form" | "code" | "text" | "preview";
/** Array of modes available for user switching */
modes?: Array<"tree" | "view" | "form" | "code" | "text" | "preview">;
/** Enable search box (tree/view/form modes only) */
search?: boolean;
/** Enable undo/redo functionality (tree/form/preview modes only) */
history?: boolean;
/** Field name for the root node (tree/view/form modes only) */
name?: string;
/** Number of indentation spaces (code/text/preview modes only) */
indentation?: number;
/** Ace editor theme (code mode only) */
theme?: string;
}Event handling configuration for responding to user interactions and data changes.
interface EventCallbacks {
/** Triggered when contents change (does not pass data) */
onChange?: () => void;
/** Triggered when JSON changes, passes the changed JSON (tree/view/form modes) */
onChangeJSON?: (json: any) => void;
/** Triggered when text changes, passes stringified JSON */
onChangeText?: (jsonString: string) => void;
/** Triggered when an error occurs */
onError?: (error: Error) => void;
/** Triggered when mode changes */
onModeChange?: (newMode: string, oldMode: string) => void;
/** Triggered when editor gains focus */
onFocus?: (event: { type: "focus"; target: any }) => void;
/** Triggered when editor loses focus */
onBlur?: (event: { type: "blur"; target: any }) => void;
/** Triggered on node selection change (tree mode only) */
onSelectionChange?: (start?: SerializableNode, end?: SerializableNode) => void;
/** Triggered on text selection change (code/text modes only) */
onTextSelectionChange?: (
start: { row: number; column: number },
end: { row: number; column: number },
text: string
) => void;
/** Triggered on node events (tree/view/form modes only) */
onEvent?: (node: NodeEvent, event: Event) => void;
}Configuration for JSON schema validation and custom validation functions.
interface ValidationOptions {
/** JSON schema object for validation */
schema?: object;
/** Referenced schemas for $ref properties */
schemaRefs?: { [key: string]: object };
/**
* Custom Ajv instance for validation
* IMPORTANT: JSONEditor relies on specific Ajv configuration.
* Providing different configuration (like jsonPointers: true instead of false)
* may cause JSONEditor to break due to different error formats.
*/
ajv?: any;
/** Custom validation function */
onValidate?: (json: any) => ValidationError[] | Promise<ValidationError[]>;
/** Callback for validation errors */
onValidationError?: (errors: ValidationError[]) => void;
}Visual customization options for styling and display behavior.
interface AppearanceOptions {
/** Escape unicode characters as hex codes */
escapeUnicode?: boolean;
/** Sort object keys alphabetically */
sortObjectKeys?: boolean;
/** Enable color picker for color values */
colorPicker?: boolean;
/** Show timestamp tags for timestamp values */
timestampTag?: boolean | ((node: NodeInfo) => boolean);
/** Custom timestamp formatting function */
timestampFormat?: (node: NodeInfo) => string | null;
/** Show main menu bar */
mainMenuBar?: boolean;
/** Show navigation bar (tree/view/form modes) */
navigationBar?: boolean;
/** Show status bar (code/text/preview modes) */
statusBar?: boolean;
/** Show error table on validation errors */
showErrorTable?: boolean | string[];
}Options that control editor behavior and user interaction patterns.
interface BehaviorOptions {
/** Restrict dragging to same parent node */
limitDragging?: boolean;
/** Maximum visible children before "show more" appears */
maxVisibleChilds?: number;
/** Enable sorting functionality */
enableSort?: boolean;
/** Enable transform/filter functionality */
enableTransform?: boolean;
/** Enable schema-based autocomplete suggestions */
allowSchemaSuggestions?: boolean;
}Advanced customization through callback functions for dynamic behavior.
interface CustomizationOptions {
/** Control editability of individual nodes (tree/text/code modes) */
onEditable?: (node: NodeInfo) => boolean | { field: boolean; value: boolean };
/** Add custom CSS classes to nodes */
onClassName?: (node: NodeInfo) => string | undefined;
/** Customize object/array node names */
onNodeName?: (node: NodeNameInfo) => string | undefined;
/** Customize context menus */
onCreateMenu?: (items: MenuItem[], node: MenuContext) => MenuItem[];
/** Triggered on node expand/collapse */
onExpand?: (info: { path: PathArray; isExpand: boolean; recursive: boolean }) => void;
/** Custom color picker implementation */
onColorPicker?: (
parent: HTMLElement,
color: string,
onChange: (newColor: string) => void
) => void;
}Advanced configuration for specialized use cases and integrations.
interface AdvancedOptions {
/**
* Custom Ace editor instance for code mode
* Required plugins: mode-json, worker-json, ext-searchbox, ext-language_tools
* In minimalist builds, plugins must be loaded separately
*/
ace?: any;
/** Template objects for context menu */
templates?: Template[];
/** Autocomplete configuration */
autocomplete?: AutocompleteConfig;
/** Container element for modal dialogs */
modalAnchor?: HTMLElement;
/** Container element for popup elements */
popupAnchor?: HTMLElement;
/** Language code for internationalization */
language?: string;
/** Custom translations */
languages?: { [language: string]: { [key: string]: string } };
/** Custom query creation function */
createQuery?: (json: any, queryOptions: QueryOptions) => string;
/** Custom query execution function */
executeQuery?: (json: any, query: string) => any;
/** Query language description */
queryDescription?: string;
}The full JSONEditorOptions interface combining all configuration categories.
interface JSONEditorOptions
extends CoreOptions,
EventCallbacks,
ValidationOptions,
AppearanceOptions,
BehaviorOptions,
CustomizationOptions,
AdvancedOptions {}const options = {
mode: "tree",
modes: ["tree", "code", "text"],
search: true,
history: true,
indentation: 2
};
const editor = new JSONEditor(container, options);const options = {
mode: "tree",
onChange: () => {
console.log("Content changed");
},
onChangeJSON: (json) => {
console.log("New JSON:", json);
},
onError: (error) => {
console.error("Editor error:", error);
},
onSelectionChange: (start, end) => {
console.log("Selection changed:", start, end);
}
};const schema = {
type: "object",
properties: {
name: { type: "string" },
age: { type: "number", minimum: 0 }
},
required: ["name"]
};
const options = {
mode: "tree",
schema: schema,
onValidationError: (errors) => {
errors.forEach(error => {
console.log(`Validation error: ${error.message}`);
});
}
};const options = {
mode: "tree",
onClassName: ({ path, field, value }) => {
if (field === "email") return "email-field";
if (typeof value === "number" && value < 0) return "negative-number";
},
onNodeName: ({ type, size }) => {
return type === "array" ? `[${size} items]` : `{${size} props}`;
},
templates: [
{
text: "Person",
title: "Insert Person Template",
field: "person",
value: { name: "", age: 0, email: "" }
}
]
};interface NodeInfo {
field: string;
value: any;
path: PathArray;
}
interface NodeNameInfo {
path: PathArray;
type: "object" | "array";
size: number;
value: any;
}
interface NodeEvent {
field?: string;
path: PathArray;
value?: any;
}
interface MenuItem {
text: string;
title?: string;
className?: string;
click?: () => void;
submenu?: MenuItem[];
}
interface MenuContext {
type: "single" | "multiple" | "append";
path: PathArray;
paths: PathArray[];
}
interface Template {
text: string;
title?: string;
className?: string;
field?: string;
value: any;
}
interface AutocompleteConfig {
filter?: "start" | "contain" | ((token: string, match: string | { text: string; value: any }) => boolean);
trigger?: "keydown" | "focus";
confirmKeys?: number[];
caseSensitive?: boolean;
getOptions?: (
text: string,
path: PathArray,
input: "field" | "value",
editor: JSONEditor
) => string[] | { text: string; value: any }[] | { startFrom: number; options: any[] } | Promise<any>;
}