Skip to content

Repository files navigation

@ht-rnd/json-schema-editor

A powerful headless JSON Schema editor for React. Build fully customized editors with complete UI control while leveraging battle-tested logic, validation, and state management.

Headless Architecture: Core logic via npm + optional copy-paste UI components. Use our pre-built Shadcn/ui components or build your own interface.

Features

  • Multi-Draft Support - Draft-07, 2019-09, and 2020-12 with automatic detection via $schema URI
  • All Types - string, number, integer, boolean, object, array, $ref
  • Nested Schemas - Unlimited depth for objects and arrays
  • $defs / definitions Support - Reusable definitions with $ref; emits the correct key per draft
  • Validation - AJV-powered real-time draft-aware validation
  • Combinators - allOf, anyOf, oneOf, not
  • TypeScript - Full type safety
  • Headless - Zero UI dependencies in core

Installation

npm install @ht-rnd/json-schema-editor

Optional UI components: Copy components/ui/ from this repo to your project. Requires Radix UI and Tailwind CSS.

Quick Start

Option 1: Pre-built Components

import { JsonSchemaEditor } from "@/components/ui/json-schema-editor";

function App() {
  return (
    <JsonSchemaEditor
      rootType="object"
      onChange={(schema) => console.log(schema)}
    />
  );
}

Option 2: Headless Hook

import { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";
import { FormProvider } from "react-hook-form";

function App() {
  const editor = useJsonSchemaEditor({
    rootType: "object",
    onChange: (schema) => console.log(schema),
  });

  return (
    <FormProvider {...editor.form}>
      <button onClick={editor.addField}>Add Field</button>
      {editor.fields.map((field, index) => (
        <div key={field.id}>
          <input value={field.key} />
          <button onClick={() => editor.removeField(index)}>Remove</button>
        </div>
      ))}
      <pre>{JSON.stringify(editor.schema, null, 2)}</pre>
    </FormProvider>
  );
}

API Reference

useJsonSchemaEditor(options)

Main hook for editor state management.

Options:

{
  rootType?: "object" | "array";  // Default: "object"
  defaultValue?: JSONSchema;       // Load existing schema
  onChange?: (schema: JSONSchema) => void;
}

Returns:

{
  // State
  schema: JSONSchema;
  errors: SchemaError[] | null;  // null when valid
  fields: FieldItem[];
  definitions: DefinitionItem[];
  form: UseFormReturn;
  settingsState: { isOpen: boolean; fieldPath: string | null };

  // Actions
  addField: () => void;
  removeField: (index: number) => void;
  addDefinition: () => void;
  removeDefinition: (index: number) => void;
  updateReferences: (oldKey: string, newKey: string | null) => void;  // update $ref strings when a definition key changes
  openSettings: (path: string) => void;
  closeSettings: () => void;
  handleTypeChange: (path: string, type: string) => void;
  addNestedField: (parentPath: string) => void;
  reset: () => void;
}

JsonSchemaEditor Component Props

Prop Type Default Description
rootType "object" | "array" "object" Root schema type
defaultValue JSONSchema - Initial schema to load
onChange (schema) => void - Callback on schema change
readOnly boolean false View-only mode
showOutput boolean true Show/hide JSON output panel
defaultOutputCollapsed boolean false Start the JSON output panel collapsed
className string - Additional CSS classes

Exports

// Main hook
export { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";

// Types
export type { JSONSchema, FieldItem, DefinitionItem, UseJsonSchemaEditorReturn };

// Utilities (all draft-aware: select AJV instance / emit correct defs key based on $schema)
export { validateSchema, formToSchema, schemaToForm };

// Constants
export { SCHEMA_TYPES, STRING_FORMATS, NUMBER_FORMATS, INTEGER_FORMATS };

Examples

Load Existing Schema

const editor = useJsonSchemaEditor({
  rootType: "object",
  defaultValue: {
    type: "object",
    properties: {
      username: { type: "string", minLength: 3 },
      email: { type: "string", format: "email" },
      age: { type: "integer", minimum: 18 }
    },
    required: ["username", "email"]
  }
});

Validate Data Against Schema

import Ajv from "ajv";

const ajv = new Ajv();
const validate = ajv.compile(editor.schema);
const valid = validate({ username: "john", email: "john@example.com" });

if (!valid) console.log(validate.errors);

Persist Schema Changes

const editor = useJsonSchemaEditor({
  onChange: (schema) => {
    localStorage.setItem("schema", JSON.stringify(schema));
    // Or send to API
  }
});

Contributing

Contributions welcome! See GitHub for issues and PRs.

git clone https://github.com/ht-rnd/json-schema-editor.git
npm install
npm test
npm run demo

License

Apache-2.0 © [HT-RND]

See LICENSE for more details.

About

A React library for building JSON Schema editors, providing core logic, hooks and utilities along with customizable UI components for flexible schema creation and editing.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages