You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Activiti REST返回的JSON转换为HTML表单?

我之前在做Activiti相关项目时也碰到过这个问题——它的REST接口返回的表单结构确实有自己的特殊性,通用的JSON转表单工具基本都没法直接适配,毕竟这些工具大多针对标准JSON Schema,而Activiti的返回里带了readable、writable、enumValues这类专属属性。不过其实自己实现转换逻辑并没有想象中难,下面分享几个我亲测可行的方案:

方案一:前端原生JavaScript手动转换

这是最直接的方式,直接遍历返回的formProperties数组,根据每个字段的type生成对应的HTML表单控件,同时处理必填、读写权限等属性。

function convertActivitiFormToHtml(formData) {
  // 创建表单容器
  const form = document.createElement('form');
  form.action = formData.taskUrl;
  form.method = 'POST';
  form.className = 'activiti-form';

  // 遍历每个表单属性
  formData.formProperties.forEach(prop => {
    // 跳过不可读的字段
    if (!prop.readable) return;

    const fieldWrapper = document.createElement('div');
    fieldWrapper.className = 'form-field';

    // 生成标签
    const label = document.createElement('label');
    label.htmlFor = prop.id;
    label.textContent = `${prop.name}${prop.required ? ' *' : ''}`;
    fieldWrapper.appendChild(label);

    let inputElement;
    // 根据字段类型生成对应控件
    switch (prop.type) {
      case 'string':
        inputElement = document.createElement('input');
        inputElement.type = 'text';
        break;
      case 'date':
        inputElement = document.createElement('input');
        inputElement.type = 'date';
        // 如果需要适配Activiti的日期格式(比如dd/MM/yyyy),可以搭配flatpickr这类日期插件处理
        inputElement.dataset.datePattern = prop.datePattern;
        break;
      case 'enum':
        inputElement = document.createElement('select');
        // 非必填字段添加空选项
        if (!prop.required) {
          const emptyOpt = document.createElement('option');
          emptyOpt.value = '';
          emptyOpt.textContent = '-- 请选择 --';
          inputElement.appendChild(emptyOpt);
        }
        // 添加枚举选项
        prop.enumValues.forEach(enumItem => {
          const opt = document.createElement('option');
          opt.value = enumItem.id;
          opt.textContent = enumItem.name;
          inputElement.appendChild(opt);
        });
        break;
      // 可以扩展支持boolean等其他类型
      default:
        inputElement = document.createElement('input');
        inputElement.type = 'text';
    }

    // 设置控件基础属性
    inputElement.id = prop.id;
    inputElement.name = prop.id;
    inputElement.value = prop.value || '';
    inputElement.required = prop.required;
    // 不可写字段设置为禁用状态
    if (!prop.writable) inputElement.disabled = true;

    fieldWrapper.appendChild(inputElement);
    form.appendChild(fieldWrapper);
  });

  // 添加提交按钮
  const submitBtn = document.createElement('button');
  submitBtn.type = 'submit';
  submitBtn.textContent = '提交表单';
  form.appendChild(submitBtn);

  return form;
}

// 使用示例:假设已获取到Activiti返回的JSON数据
const activitiFormJson = { /* 你的JSON数据 */ };
const generatedForm = convertActivitiFormToHtml(activitiFormJson);
document.body.appendChild(generatedForm);

这段代码的优势是灵活可控,完全适配Activiti的字段属性,不需要依赖第三方库,适合纯前端项目快速实现。

方案二:后端模板引擎渲染(Java项目适用)

如果你的项目是Java后端主导,可以在后端接收Activiti的REST返回后,用模板引擎(比如Thymeleaf、Freemarker)来渲染HTML表单,这样还能在后端统一处理日期格式转换等逻辑。

以Thymeleaf为例,模板片段如下:

<form th:action="${formData.taskUrl}" method="post" class="activiti-form">
  <div th:each="prop : ${formData.formProperties}" 
       th:if="${prop.readable}" 
       class="form-field">
    <label th:for="${prop.id}" 
           th:text="${prop.name + (prop.required ? ' *' : '')}">
    </label>

    <!-- 字符串类型字段 -->
    <input th:if="${prop.type == 'string'}"
           th:id="${prop.id}"
           th:name="${prop.id}"
           th:value="${prop.value}"
           th:required="${prop.required}"
           th:disabled="${!prop.writable}"
           type="text" />

    <!-- 日期类型字段 -->
    <input th:if="${prop.type == 'date'}"
           th:id="${prop.id}"
           th:name="${prop.id}"
           th:value="${#dates.format(prop.value, prop.datePattern)}"
           th:required="${prop.required}"
           th:disabled="${!prop.writable}"
           type="date" />

    <!-- 枚举类型字段 -->
    <select th:if="${prop.type == 'enum'}"
            th:id="${prop.id}"
            th:name="${prop.id}"
            th:required="${prop.required}"
            th:disabled="${!prop.writable}">
      <option th:if="${!prop.required}" value="">-- 请选择 --</option>
      <option th:each="enumItem : ${prop.enumValues}"
              th:value="${enumItem.id}"
              th:text="${enumItem.name}">
      </option>
    </select>
  </div>
  <button type="submit">提交表单</button>
</form>

这种方式适合后端需要对表单数据做预处理的场景,比如日期格式的统一转换,或者结合业务逻辑动态调整字段属性。

方案三:适配现有JSON Schema表单库(适合前端框架项目)

如果你的项目用了React、Vue等前端框架,也可以把Activiti的JSON结构转换成标准JSON Schema,再用成熟的表单库(比如react-jsonschema-form)生成表单。需要先写一个转换函数:

function activitiToJsonSchema(formData) {
  const schema = {
    type: 'object',
    properties: {},
    required: []
  };

  formData.formProperties.forEach(prop => {
    if (!prop.readable) return;
    
    const propSchema = {};
    switch (prop.type) {
      case 'string':
        propSchema.type = 'string';
        break;
      case 'date':
        propSchema.type = 'string';
        propSchema.format = 'date';
        break;
      case 'enum':
        propSchema.type = 'string';
        propSchema.enum = prop.enumValues.map(item => item.id);
        propSchema.enumNames = prop.enumValues.map(item => item.name);
        break;
    }

    schema.properties[prop.id] = propSchema;
    if (prop.required) schema.required.push(prop.id);
  });

  // 额外添加UI配置,处理读写权限
  const uiSchema = {};
  formData.formProperties.forEach(prop => {
    if (!prop.writable) {
      uiSchema[prop.id] = {
        'ui:disabled': true
      };
    }
  });

  return { schema, uiSchema };
}

转换后就可以用对应的框架表单库来生成表单,这种方式适合已经在用框架表单库的项目,能复用现有组件体系。


内容的提问来源于stack exchange,提问作者Tomato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:04:10