vue-json-ui-editor
v3.1.0
Published
A Vue 3 JSON Schema based form editor component with TypeScript support
Maintainers
Readme
json-editor
A Vue 3 JSON Schema based form editor component. Edit JSON in UI form with JSON Schema and element-plus, with full TypeScript support.

Versions & Branches
本仓库通过不同分支维护多个 Vue 版本的发布。请根据你的 Vue 版本选择对应分支:
| Branch | Version | Vue | UI Library | Status |
|--------|---------|-----|------------|--------|
| main | 3.x | Vue 3 (^3.5.0) | element-plus (^2.11.1) | ✅ Active |
| master | 2.x | Vue 2 (^2.7.16) | element-ui (^2.15.14) | 🛠️ Maintenance |
| v1 | 1.x | Vue 2 (^2.5.17) | element-ui (^2.4.11) | ⚰️ Legacy |
Install
npm install vue-json-ui-editor
# or
pnpm add vue-json-ui-editor
vue-json-ui-editor3.x targets Vue 3 and is designed to work with element-plus. For Vue 2, see themaster(2.x) orv1(1.x) branch.
Use
<template>
<json-editor ref="jsonEditorRef" :schema="schema" v-model="model">
<el-button type="primary" @click="submit">Submit</el-button>
<el-button @click="reset">Reset</el-button>
</json-editor>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import JsonEditor from 'vue-json-ui-editor';
const schema = {
type: 'object',
title: 'vue-json-editor demo',
properties: {
name: { type: 'string' },
email: { type: 'string' },
},
};
const model = ref({ name: 'Yourtion' });
const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>();
function submit() {
// jsonEditorRef.value?.form() returns the underlying element-plus form instance
jsonEditorRef.value?.form().validate((valid: boolean) => {
if (!valid) {
jsonEditorRef.value?.setErrorMessage('Please fill out the required fields');
}
});
}
function reset() {
jsonEditorRef.value?.reset();
}
</script>
json-editorrenders with native HTML elements by default. To style it with element-plus, register the components via the staticJsonEditor.setComponent(type, component, option?)API — see the example.Complete working example: example/components/Subscription.vue Schema: example/schema/newsletter.json
props
schemaObject (required) The JSON Schema object. Use thev-ifdirective to load asynchronous schema.v-model/modelValueObject (optional)default: {}Two-way binding for the form data. In Vue 3,v-modelbinds to themodelValueprop.auto-completeString (optional) Whether the value of the control can be automatically completed by the browser. Possible values:off,on.no-validateBoolean (optional)default: falseIndicates that the form is not to be validated when submitted.input-wrapping-classString (optional) Wraps each field's controls in a<div class="...">. Leaveundefinedto disable input wrapping.componentsObject (optional)default: undefinedPer-instance component overrides. When provided, these are merged over the global defaults registered viaJsonEditor.setComponent, so multiple<json-editor>instances on the same page can each use a different UI library without polluting each other. Keys are element types (e.g.text,select,form,label); values may be a full{ component, option }config or a shorthand component name/object. Leaveundefinedto fall back to the global registry.
// Two editors on the same page, each with its own text widget:
<json-editor :schema="a" :components="{ text: CompA }" />
<json-editor :schema="b" :components="{ text: CompB }" />events
update:modelValueEmitted (forv-model) whenever a field value changes.changeFired when a change to an element's value is committed by the user.submitFired when the form is submitted and passes validation.invalidFired when a submittable element has been checked and doesn't satisfy its constraints.
methods
Exposed via a template ref to the <json-editor> instance (e.g. jsonEditorRef.value):
input(name)Get a form input reference.form()Get the rendered form component instance (e.g. the element-plusel-form), so you can call.validate()/.resetFields()on it.checkValidity()Checks whether the form satisfies its constraints. Returnsboolean.validate()Async validation shortcut — delegates to the underlying form component'svalidate()when available.reset()Reset the value of all elements of the form to the initialmodelValue.setErrorMessage(message)Set an error message (rendered via theerrorcomponent type).clearErrorMessage()Clear the error message.getFields()Return the current parsed field tree (including$subcontainers for nested objects).vmThe reactive view-model ({ model, fields, error }), for advanced consumers and option-callback access.
static API
JsonEditor.setComponent(type, component, option?)Register a Vue component (or native tag name) for a given field/elementtype(e.g.form,label,email,text,select,error, …).optionmay be a plain object or a factory callback({ vm, field, item }) => propsObject. This is how you wire the editor to a UI library like element-plus.
JsonEditor.setComponent('text', 'el-input');
JsonEditor.setComponent('form', 'el-form', ({ vm }) => ({ model: vm.model, rules: {} }));
JsonEditor.setComponent('error', 'el-alert', ({ vm }) => ({ type: 'error', title: vm.error }));Note on
labelwith element-plus:el-form-itemreads its label text from thelabelprop (not the default slot), so thelabelregistration callback must returnlabel: field.labelin addition toprop: field.name. See example/components/Subscription.vue.
Wiring specific widgets via schema attrs
The widget for a field is chosen by attrs.type in its schema property (the editor reads schema.attrs as the field descriptor). Register the type once with setComponent, then drive it from the schema:
JsonEditor.setComponent('switch', 'el-switch');
JsonEditor.setComponent('date', 'el-date-picker');
// schema:
{ active: { type: 'boolean', attrs: { type: 'switch' } } }
{ createdAt: { type: 'string', format: 'date-time', attrs: { type: 'date' } } }Schema features
disabled: trueandreadOnly: trueon a property disable/readonly the rendered input (readOnly also implies disabled).- Nested objects (
type: 'object'withproperties) render in a sub-container with the object'stitle(.sub-title) anddescription(.sub-description). - Object arrays (
type: 'array'withitems: { type: 'object', properties }) render as an editable list of sub-form rows. Each array renders a header (field label + add button,.json-editor-array-header) and one row per item (.json-editor-array-rowwith the item's sub-fields + a remove button). The add/remove buttons are registered via thearrayadd/arrayremovecomponent types (default native<button>; register asel-button/ icon buttons for UI library styling — see example/components/Subscription.vue). Arrays work at any nesting depth, including inside nested objects. - Choice arrays (
array+enum/oneOf/anyOf) render as a singleselect/ radio group / checkbox group.
Advanced: reusing the array renderer
The object-array add/remove logic is extracted into a standalone, framework-agnostic module so it can be reused or unit-tested in isolation:
import { createArrayRenderer, type ArrayRendererDeps } from 'vue-json-ui-editor';
const renderer = createArrayRenderer({
model, onChange, getComp, resolveComp, elementOptions, wrapChild, renderInput,
} satisfies ArrayRendererDeps);
renderer.render(field, fieldName); // → vnode[] for the whole array (header + rows)
renderer.addRow(fieldName);
renderer.removeRow(fieldName, index);ArrayRendererDeps declares exactly what the renderer needs (a reactive model, an onChange notifier, and the component-resolution helpers), so it isn't coupled to JsonEditor's setup closure.
TypeScript
This package ships with bundled type declarations. You can import types directly:
import JsonEditor, { type JsonSchema } from 'vue-json-ui-editor';
// newly exported types (v3.1+):
import type {
JsonEditorStatic, // the setComponent static method signature
JsonEditorInstance, // exposed instance methods (form/validate/reset/getFields/vm)
ComponentConfig, OptionContext, VmContext, ComponentsMap,
ArrayRendererDeps, // for createArrayRenderer
} from 'vue-json-ui-editor';Development
pnpm install # install dependencies
pnpm dev # start the example app (Vite)
pnpm build:lib # build the publishable library bundle
pnpm test # run unit tests (Vitest)
pnpm check # type-check + format + testLicense
MIT © Yourtion
