
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
json-schema-builder-react
Advanced tools
A React component library for building and editing JSON schemas visually
A beautiful, interactive React component for building and editing JSON schemas visually. Built with TypeScript, Tailwind CSS, and Radix UI.
npm install json-schema-builder-react
# or
yarn add json-schema-builder-react
# or
pnpm add json-schema-builder-react
This library requires the following peer dependencies to be installed in your project:
This library uses shadcn/ui components. You'll need to set up shadcn/ui and install the required components:
# Initialize shadcn/ui (if not already done)
npx shadcn@latest init
# Install required components
npx shadcn@latest add button dialog input select checkbox tooltip card label textarea
npm install @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot @radix-ui/react-tooltip lucide-react class-variance-authority clsx tailwind-merge
This library uses Tailwind CSS utility classes. You'll need Tailwind CSS configured in your project.
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Add the library to your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./node_modules/json-schema-builder-react/**/*.{js,jsx}', // Add this line
],
theme: {
extend: {},
},
plugins: [],
};
Create or update postcss.config.js in your project root:
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Add to your main CSS file (e.g., src/index.css):
@tailwind base;
@tailwind components;
@tailwind utilities;
Note: The library components will automatically use your project's Tailwind theme (colors, spacing, etc.).
import { useState } from 'react';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
function App() {
const [schema, setSchema] = useState({
type: 'object',
properties: {},
required: []
});
return (
<JsonSchemaBuilder
schema={schema}
onChange={setSchema}
/>
);
}
import { useState } from 'react';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
function App() {
const [schema, setSchema] = useState({
type: 'object',
title: 'User Profile',
properties: {
name: {
type: 'string',
minLength: 2,
maxLength: 50
},
age: {
type: 'integer',
minimum: 0,
maximum: 120
}
},
required: ['name']
});
return (
<JsonSchemaBuilder
schema={schema}
onChange={(newSchema) => {
setSchema(newSchema);
// Save to backend, localStorage, etc.
localStorage.setItem('schema', JSON.stringify(newSchema));
}}
/>
);
}
import { useState } from 'react';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
function App() {
const [schema, setSchema] = useState({
type: 'object',
properties: {},
required: []
});
return (
<JsonSchemaBuilder
schema={schema}
onChange={setSchema}
showMetadata={true}
showOutput={true}
className="h-[600px]"
typeLabels={{
string: 'Text',
boolean: 'Yes/No',
object: 'Form',
array: 'List',
}}
propertyLabel={{
singular: 'field',
plural: 'fields'
}}
/>
);
}
Since the component is fully controlled, you can implement undo/redo easily:
import { useState } from 'react';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
function App() {
const [history, setHistory] = useState([{
type: 'object',
properties: {},
required: []
}]);
const [currentIndex, setCurrentIndex] = useState(0);
const currentSchema = history[currentIndex];
const handleChange = (newSchema) => {
const newHistory = history.slice(0, currentIndex + 1);
newHistory.push(newSchema);
setHistory(newHistory);
setCurrentIndex(currentIndex + 1);
};
const undo = () => {
if (currentIndex > 0) {
setCurrentIndex(currentIndex - 1);
}
};
const redo = () => {
if (currentIndex < history.length - 1) {
setCurrentIndex(currentIndex + 1);
}
};
return (
<div>
<div className="toolbar">
<button onClick={undo} disabled={currentIndex === 0}>
Undo
</button>
<button onClick={redo} disabled={currentIndex === history.length - 1}>
Redo
</button>
</div>
<JsonSchemaBuilder
schema={currentSchema}
onChange={handleChange}
/>
</div>
);
}
By default, property keys are immutable after creation to prevent breaking existing references in your codebase. However, you can enable key editing with the keyEditable prop:
import { useState } from 'react';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
function App() {
const [schema, setSchema] = useState({
type: 'object',
properties: {
user_name: {
type: 'string',
title: 'User Name'
}
},
required: []
});
return (
<JsonSchemaBuilder
schema={schema}
onChange={setSchema}
keyEditable={true} // ⚠️ Allows changing keys after creation
/>
);
}
⚠️ Warning: Enabling keyEditable allows users to change property keys even after they've been created. This can break existing code that references these keys. Use with caution, primarily in development environments or when you have proper migration strategies in place.
If you only need to edit a single property without the full builder UI, you can use the PropertyEditDialog component:
import { useState } from 'react';
import { PropertyEditDialog } from 'json-schema-builder-react';
import type { PropertyData } from 'json-schema-builder-react';
function PropertyEditor() {
const [isOpen, setIsOpen] = useState(false);
const [property, setProperty] = useState<PropertyData>({
id: '1',
key: 'username',
title: 'Username',
type: 'string',
required: true,
minLength: 3,
maxLength: 50,
});
return (
<>
<button onClick={() => setIsOpen(true)}>
Edit Property
</button>
<PropertyEditDialog
property={property}
open={isOpen}
onOpenChange={setIsOpen}
onSave={(updated) => {
setProperty(updated);
// Save to your backend or state management
console.log('Updated property:', updated);
}}
isNewProperty={false}
showRegex={true}
typeLabels={{
string: 'Text',
number: 'Number',
boolean: 'Yes/No'
}}
/>
</>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
schema | object | Required | The JSON schema object (controlled) |
onChange | (schema: any) => void | Required | Callback when schema changes |
showMetadata | boolean | false | Show metadata fields (title, description, version) |
showImport | boolean | true | Show import button |
showClear | boolean | true | Show clear all button |
showOutput | boolean | true | Show JSON output panel |
showHeader | boolean | true | Show header with action buttons |
showSummary | boolean | false | Show summary at bottom |
showRegex | boolean | false | Show regex pattern field for strings |
keyEditable | boolean | false | Allow editing property keys after initialization (⚠️ may break references) |
className | string | "h-screen" | Custom className for container |
typeLabels | TypeLabels | Default labels | Custom labels for property types |
propertyLabel | { singular: string, plural: string } | { singular: 'property', plural: 'properties' } | Custom labels for properties |
| Prop | Type | Default | Description |
|---|---|---|---|
property | PropertyData | Required | The property object to edit |
open | boolean | Required | Whether the dialog is open |
onOpenChange | (open: boolean) => void | Required | Callback when dialog open state changes |
onSave | (property: PropertyData) => void | Required | Callback when property is saved |
isArrayItem | boolean | false | Whether this property is an array item |
isNewProperty | boolean | false | Whether this is a new property (affects key editing) |
propertyLabel | { singular: string, plural: string } | { singular: 'Property', plural: 'Properties' } | Custom labels |
showRegex | boolean | false | Show regex pattern field for strings |
keyEditable | boolean | false | Allow editing property key |
typeLabels | TypeLabels | Default labels | Custom labels for property types |
You can customize how property types are displayed to your users:
import { useState } from 'react';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
import type { TypeLabels } from 'json-schema-builder-react';
const customLabels: TypeLabels = {
string: 'Text',
number: 'Number',
integer: 'Whole Number',
boolean: 'Yes/No',
object: 'Form',
array: 'List',
null: 'Empty'
};
function App() {
const [schema, setSchema] = useState({
type: 'object',
properties: {},
required: []
});
return (
<JsonSchemaBuilder
schema={schema}
onChange={setSchema}
typeLabels={customLabels}
/>
);
}
This affects:
Available types to customize:
string - Default: "String"number - Default: "Number"integer - Default: "Integer"boolean - Default: "Boolean"object - Default: "Object"array - Default: "Array"null - Default: "Null"JsonSchemaBuilder - Main builder component (controlled)JsonSchemaBuilderProps - Props for the main componentTypeLabels - Type for customizing property type labelsThe controlled component pattern makes it easy to integrate with any state management solution:
import { useSelector, useDispatch } from 'react-redux';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
import { updateSchema } from './schemaSlice';
function App() {
const schema = useSelector(state => state.schema);
const dispatch = useDispatch();
return (
<JsonSchemaBuilder
schema={schema}
onChange={(newSchema) => dispatch(updateSchema(newSchema))}
/>
);
}
import { useSchemaStore } from './store';
import { JsonSchemaBuilder } from 'json-schema-builder-react';
function App() {
const { schema, setSchema } = useSchemaStore();
return (
<JsonSchemaBuilder
schema={schema}
onChange={setSchema}
/>
);
}
# Install dependencies
npm install
# Run demo app in development mode
npm run dev
# Build the library
npm run build:lib
# Build the demo app
npm run build
# Deploy demo to GitHub Pages
npm run deploy
If you see this warning:
A PostCSS plugin did not pass the `from` option to `postcss.parse`
Solution: Make sure you have a postcss.config.js file in your project root:
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
And verify your tailwind.config.js includes the library path:
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./node_modules/json-schema-builder-react/**/*.{js,jsx}',
],
// ...
};
Make sure you:
MIT © Martin Arusalu
Contributions are welcome! Please feel free to submit a Pull Request.
FAQs
A React component library for building and editing JSON schemas visually
We found that json-schema-builder-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.