Skip to content

Commit

Permalink
✨ [#4980] Add function to generate JSON schema from a form and list o…
Browse files Browse the repository at this point in the history
…f variables to include

Also updated the JSON dump plugin
  • Loading branch information
viktorvanwijk committed Jan 9, 2025
1 parent 6affd84 commit 4784718
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 14 deletions.
72 changes: 71 additions & 1 deletion src/openforms/forms/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import random
import string
import zipfile
from typing import Any
from typing import Any, Sequence
from uuid import uuid4

from django.conf import settings
Expand All @@ -16,9 +16,13 @@
from rest_framework.test import APIRequestFactory

from openforms.formio.migration_converters import CONVERTERS, DEFINITION_CONVERTERS
from openforms.formio.registry import register as component_registry
from openforms.formio.utils import iter_components
from openforms.typing import JSONObject
from openforms.variables.constants import FormVariableSources
from openforms.variables.registry import (
register_static_variable as static_variable_registry,
)

from .api.datastructures import FormVariableWrapper
from .api.serializers import (
Expand Down Expand Up @@ -129,6 +133,72 @@ def form_to_json(form_id: int) -> dict:
return resources


# TODO-4980: what should the name be? Do we need the submission, or is just the form
# sufficient here?
# TODO-4980: pass form_id instead of the form?
def form_variables_to_json_schema(
form: Form, variables_to_include: Sequence[str]
) -> JSONObject:
"""Generate a JSON schema from a form, for the specified variables.
:param form: The form to generate JSON schema for.
:param variables_to_include: A sequence of variables to include in the schema.
:returns: A JSON schema representing the form variables.
"""

# Handle static variables
static_var_properties = {
key: static_variable_registry[key].as_json_schema()
for key in variables_to_include
if key in static_variable_registry
}

# Handle form variables
all_form_vars = {var.key: var for var in form.formvariable_set.all()}

# TODO-4980: add to FormVariable?
def get_json_schema_from_form_variable(form_variable):
form_def = form_variable.form_definition

component = form_def.configuration_wrapper.component_map[form_variable.key]
component_plugin = component_registry[component["type"]]

return component_plugin.as_json_schema(component)

form_var_properties = {
key: get_json_schema_from_form_variable(all_form_vars[key])
for key in variables_to_include
if key in all_form_vars
}

# Required
def is_required(form_variable):
form_def = form_variable.form_definition
component = form_def.configuration_wrapper.component_map[form_variable.key]

validate = component.get("validate", {})
return validate.get("required", False)

required_form_variables = [
var for var in form_var_properties.keys() if is_required(all_form_vars[var])
]

required = [*static_var_properties.keys(), *required_form_variables]

# Result
var_properties = {**static_var_properties, **form_var_properties}
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": var_properties,
"required": required,
"additionalProperties": False,
}

return schema


def export_form(form_id, archive_name=None, response=None):
resources = form_to_json(form_id)

Expand Down
33 changes: 20 additions & 13 deletions src/openforms/registrations/contrib/json_dump/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from zgw_consumers.client import build_client

from openforms.forms.utils import form_variables_to_json_schema
from openforms.formio.typing import Component
from openforms.submissions.models import Submission, SubmissionValueVariable, \
SubmissionFileAttachment
Expand Down Expand Up @@ -38,19 +39,25 @@ def register_submission(
self.process_variables(submission, values)

# Generate schema
# TODO: will be added in #4980. Hardcoded example for now.
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"static_var_1": {"type": "string", "pattern": "^cool_pattern$"},
"form_var_1": {"type": "string"},
"form_var_2": {"type": "string"},
"attachment": {"type": "string", "contentEncoding": "base64"},
},
"required": ["static_var_1", "form_var_1", "form_var_2"],
"additionalProperties": False,
}
schema = form_variables_to_json_schema(submission.form, options["form_variables"])

# TODO-4980: this can be cleaned up probably
# Change schema of files, as we do some custom processing in this plugin
attachment_vars = [
var for var in submission.form.formvariable_set.all()
if var.key in set(options["form_variables"]).difference(form_vars)
]
for variable in attachment_vars:
form_def = variable.form_definition
component = form_def.configuration_wrapper.component_map[variable.key]
# TODO-4980: enable this when the attachment processing is cleaned up
# multiple = component.get("multiple", False)
multiple = False

base = {"type": "string", "format": "base64"}
schema["properties"][variable.key] = (
{"type": "array", "items": base} if multiple else base
)

# Send to the service
json = {"values": values, "schema": schema}
Expand Down

0 comments on commit 4784718

Please sign in to comment.