Ver Fonte

JSON editor JSONSchema validation (#4012)

Added JSONSchema validation to json_editor. 

New method `json_editor.add_validation(schema)` will enable validation
on the json_editor component.

---

Feature request: #4003

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
jm-amt há 5 meses atrás
pai
commit
f6e13776ac

+ 10 - 1
nicegui/elements/json_editor.js

@@ -1,4 +1,4 @@
-import { JSONEditor } from "standalone";
+import { JSONEditor, createAjvValidator } from "standalone";
 
 export default {
   template: "<div></div>",
@@ -9,6 +9,8 @@ export default {
     this.properties.onSelect = (selection) => {
       this.$emit("select", { selection: selection });
     };
+
+    this.checkValidation();
     this.editor = new JSONEditor({
       target: this.$el,
       props: this.properties,
@@ -21,8 +23,14 @@ export default {
     this.destroyEditor();
   },
   methods: {
+    checkValidation() {
+      if (this.schema !== undefined) {
+        this.properties.validator = createAjvValidator({ schema: this.schema, schemaDefinitions: {}, ajvOptions: {} });
+      }
+    },
     update_editor() {
       if (this.editor) {
+        this.checkValidation();
         this.editor.updateProps(this.properties);
       }
     },
@@ -43,5 +51,6 @@ export default {
   },
   props: {
     properties: Object,
+    schema: Object,
   },
 };

+ 5 - 0
nicegui/elements/json_editor.py

@@ -19,6 +19,7 @@ class JsonEditor(Element, component='json_editor.js', dependencies=['lib/vanilla
                  properties: Dict, *,
                  on_select: Optional[Handler[JsonEditorSelectEventArguments]] = None,
                  on_change: Optional[Handler[JsonEditorChangeEventArguments]] = None,
+                 schema: Optional[Dict] = None,
                  ) -> None:
         """JSONEditor
 
@@ -29,10 +30,14 @@ class JsonEditor(Element, component='json_editor.js', dependencies=['lib/vanilla
         :param properties: dictionary of JSONEditor properties
         :param on_select: callback which is invoked when some of the content has been selected
         :param on_change: callback which is invoked when the content has changed
+        :param schema: optional `JSON schema <https://json-schema.org/>`_ for validating the data being edited
         """
         super().__init__()
         self._props['properties'] = properties
 
+        if schema:
+            self._props['schema'] = schema
+
         if on_select:
             self.on_select(on_select)
 

+ 7 - 0
tests/test_json_editor.py

@@ -19,3 +19,10 @@ def test_json_editor_methods(screen: Screen):
 
     screen.click('Get Data')
     screen.should_contain("Data: {'json': {'a': 1, 'b': 2}}")
+
+
+def test_json_editor_validation(screen: Screen):
+    ui.json_editor({'content': {'json': {'x': 0}}}, schema={'type': 'object', 'properties': {'x': {'type': 'string'}}})
+
+    screen.open('/')
+    screen.should_contain('must be string')

+ 33 - 0
website/documentation/content/json_editor_documentation.py

@@ -23,6 +23,39 @@ def main_demo() -> None:
                    on_change=lambda e: ui.notify(f'Change: {e}'))
 
 
+@doc.demo('Validation', '''
+    You can use the `schema` parameter to define a [JSON schema](https://json-schema.org/) for validating the data being edited.
+    In this demo, the editor will warn if the data does not match the schema:
+
+    - `id` must be an integer
+    - `name` must be a string
+    - `price` must be a number greater than 0
+''')
+def schema_demo() -> None:
+    schema = {
+        'type': 'object',
+        'properties': {
+            'id': {
+                'type': 'integer',
+            },
+            'name': {
+                'type': 'string',
+            },
+            'price': {
+                'type': 'number',
+                'exclusiveMinimum': 0,
+            },
+        },
+        'required': ['id', 'name', 'price'],
+    }
+    data = {
+        'id': 42,
+        'name': 'Banana',
+        'price': 15.0,
+    }
+    ui.json_editor({'content': {'json': data}}, schema=schema)
+
+
 @doc.demo('Run methods', '''
     You can run methods of the JSONEditor instance using the `run_editor_method` method.
     This demo shows how to expand and collapse all nodes and how to get the current data.