JsonSchemaForm
Render a JSON Schema as a native form — create, edit and read-only view modes, nested objects, arrays and a root array, with the web schema-to-field mapping.
Installation
pnpm dlx @docyrus/cli add @docyrus/rn-json-schema-formpnpm add tailwind-variantsUsage
import { JsonSchemaForm } from '@/components/docyrus-native/json-schema-form';
import { type JsonSchema } from '@/hooks/docyrus-native/use-docyrus-data-source-json-schema';
const schema: JsonSchema = {
type: 'object',
title: 'Customer',
required: ['name', 'email'],
properties: {
name: { type: 'string', title: 'Name' },
email: { type: 'string', format: 'email' },
tier: { type: 'string', enum: ['free', 'pro', 'enterprise'] },
address: {
type: 'object',
properties: { city: { type: 'string' }, zip: { type: 'string' } }
},
tags: { type: 'array', items: { type: 'string' } }
}
};
export function CustomerForm() {
return (
<JsonSchemaForm
schema={schema}
mode="create"
onChange={value => console.log(value)}
onSubmit={async value => save(value)} />
);
}Pair it with useDocyrusDataSourceJsonSchema to build the schema from a data source's fields.
Schema → field mapping
| Schema | Field |
|---|---|
enum with ≤ 4 values | field-radioGroup (labels from x-enumNames / enumNames / x-enum-labels / x-enumLabels, else humanized) |
enum with > 4 values | field-select |
boolean | field-switch |
number / integer | field-number |
string + contentMediaType: application/json | Monospace code input with JSON parse validation (value stays a string) |
format: email / uri / url | field-email / field-url |
format: date / date-time / datetime / time | field-date / field-dateTime / field-time |
format: password / color / hex-color | field-password / field-color |
format: textarea / multiline, or maxLength > 160 | field-textarea |
other string | field-text |
object | Outlined Card group (root object renders flat) |
array | SchemaRepeater (minItems / maxItems honoured); tuple items supported |
Inputs render through DocyFieldDynamic; mode="view" renders values through DocyValueDynamic. Enum values keep their original JSON type (strings, numbers, booleans, null). Empty strings / nulls are dropped from the emitted value, and empty nested objects / arrays are omitted (the root is always emitted).
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
schema | JsonSchema | — | Required. Root object or root array schema |
data | Record<string, unknown> | unknown[] | null | — | Initial / external value. External changes re-seed the form unless they echo the last emitted value |
mode | 'create' | 'edit' | 'view' | 'create' | view renders read-only values |
disabled | boolean | — | Disable every input and the submit button |
submitLabel | string | 'Save' | Full-width submit button label (rendered only with onSubmit) |
onChange | (value: JsonSchemaFormData) => void | — | Called with the denormalized value on every change |
onSubmit | (value: JsonSchemaFormData) => void | Promise<void> | — | Called on submit after required + JSON validation pass; the button shows a spinner while it resolves |
emptyState | ReactNode | — | Rendered for an object without properties or an empty array (view mode) |
className | string | — | Container className |
Components
| Component | Description |
|---|---|
JsonSchemaForm | Schema-driven form (create / edit / view) |
Type Exports
| Type | Description |
|---|---|
JsonSchemaFormProps | Props for JsonSchemaForm |
JsonSchemaFormMode | 'create' | 'edit' | 'view' |
JsonSchemaFormData | Record<string, unknown> | Array<unknown> |
JsonSchema itself is exported by use-docyrus-data-source-json-schema.
Differences from web
- No
@tanstack/react-form— state is a plain immutable value tree inside the component. - Always a single column;
refand HTML div attributes are dropped (classNameis kept). - On submit,
requiredproperties and JSON inputs are validated and errors are shown inline (web submits without schema validation).
Translation keys
ui.jsonSchemaForm.submit, ui.jsonSchemaForm.form, ui.jsonSchemaForm.group, ui.jsonSchemaForm.item, ui.jsonSchemaForm.add, ui.jsonSchemaForm.noFields, ui.jsonSchemaForm.noItems, ui.jsonSchemaForm.required, ui.jsonSchemaForm.invalidJson (English fallbacks; the web component hardcodes this copy).