Skip to content

ht-rnd/json-schema-editor

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

License

Stars

Watchers

Forks

Contributors