手把手教你通过JSON Schema判断BpmnJS元素属性结构~

简介: 手把手教你通过JSON Schema判断BpmnJS元素属性结构~

前言


在上一篇文章 手把手教你玩转BpmnJS元素属性更新 一文中,跟大家讲解了 如何通过已有的JSON schema 定义与完整 XML 来解析属性结构通过两个官方 API 更新属性的方式及注意事项


那么假设现在只有一个 JSON Schema 文件,怎么判断属性的构成呢?文本就带大家分析 如何从JSON Schema 判断属性结构


1. 分析 JSON Schema


该文件的每个字段的具体定义和编写方式,具体请查看 BpmnJS自定义描述文件说明。但是因为平时了解到大家对自定义这一块一般需求比较少,所以这里就用 camunda 团队新出的zeebe引擎来举例吧,这也是讨论群里一个小伙伴问我的问题。


完整的 JSON 文件请查看bpmn-process-designer/packages/moddle-extensions/zeebe.json,这里节选了ioMapping 输入输出配置


{
types: [
    {
      "name": "ZeebeServiceTask",
      "extends": [
        "bpmn:ServiceTask",
        "bpmn:BusinessRuleTask",
        "bpmn:ScriptTask",
        "bpmn:SendTask",
        "bpmn:EndEvent",
        "bpmn:IntermediateThrowEvent"
      ],
      "properties": [
        {
          "name": "retryCounter",
          "type": "String",
          "isAttr": true
        }
      ]
    },
    {
      "name": "IoMapping",
      "superClass": [
        "Element"
      ],
      "properties": [
        {
          "name": "ioMapping",
          "type": "IoMapping"
        },
        {
          "name": "inputParameters",
          "isMany": true,
          "type": "Input"
        },
        {
          "name": "outputParameters",
          "isMany": true,
          "type": "Output"
        }
      ],
      "meta": {
        "allowedIn": [
          "bpmn:CallActivity",
          "bpmn:Event",
          "bpmn:ReceiveTask",
          "zeebe:ZeebeServiceTask",
          "bpmn:SubProcess"
        ]
      }
    },
    {
      "name": "InputOutputParameter",
      "properties": [
        {
          "name": "source",
          "isAttr": true,
          "type": "String"
        },
        {
          "name": "target",
          "isAttr": true,
          "type": "String"
        }
      ]
    },
    {
      "name": "Input",
      "superClass": [
        "InputOutputParameter"
      ],
      "meta": {
        "allowedIn": [
          "bpmn:CallActivity",
          "zeebe:ZeebeServiceTask",
          "bpmn:SubProcess"
        ]
      }
    },
    {
      "name": "Output",
      "superClass": [
        "InputOutputParameter"
      ],
      "meta": {
        "allowedIn": [
          "bpmn:CallActivity",
          "bpmn:Event",
          "bpmn:ReceiveTask",
          "zeebe:ZeebeServiceTask",
          "bpmn:SubProcess"
        ]
      }
    }
]
}


🚀 这里也算是一点小技巧:只要是 types 数组中的某一个定义的properties 属性配置中如果这个属性的 type 不是 Number、Boolean、String 这几个基础类型,而是 JSON Schema 中定义的类型的话,通常这个属性都是绑定一个 通过 moddle.create 创建的对应类型的实例


1.1 分析 IoMapping


首先查看这个类型的 supperClass 或者 extends 字段,这里定义的是supperClass:[Element],说明这个属性基本上在 XML 文件中都体现为一个标签,并且标签名为zeebe:ioMapping


然后就是 meta 字段,一般这个字段里面会有一个 allowedIn 的数组格式的字段,表示 该属性或者标签(IoMapping)允许被配置/插入哪些类型的元素/标签中,通过 通配符 * 表示允许插入所有标签/属性中。此时根据配置 IoMapping 标签可以被插入到  SubProcess 子流程、CallActivity 调用任务、zeebe:ZeebeServiceTask Zeebe服务任务中


zeebe:ZeebeServiceTask的定义中,则是用extend扩展原来的ServiceTas等类型元素的,所以IoMapping 定义里 allowedIn 中的 ZeebeServiceTask 其实就可以理解为 ServiceTask 等元素的替代指示


最后分析 properties 配置,可以看到IoMapping 接收三个属性配置


  • ioMapping:类型就是IoMapping,表示这个标签内部还可以插入 IoMapping 标签,即支持嵌套


  • inputParameters:类型为Input,且isMany 为 true,表示这里是一个 数组形式,在 js 中体现为**inputParameters: []**


  • outputParameters:类型为Output,其他的信息与inputParameters一致


总结:


IoMapping 在 xml 中体现为一个标签形式,内部可以继续插入 IoMapping 标签;并且接收其他两个属性 inputParameters 和 outputParameters。


并且 inputParameters 与 outputParameters 都不是简单的数据类型,而且是数组格式,所以给这两个属性设置属性值时,内部的属性也需要通过 moddle.create 创建实例。


在我们创建一个 IoMapping 实例时,步骤和结果如下:


const moddle = modeler.get('moddle')
const ioMapping = moddle.create('zeebe:IoMapping', {inputParameters: [], outputParameters: []})
// 结果如下:
IoMapping = {
    $type: 'zeebe:IoMapping',
    inputParameters: [],
    outputParameters: []
}


1.2 ZeebeServiceTask 没有 IoMapping


虽然分析了 IoMapping 之后,知道了这个属性在配置时该怎么操作;但是,在zeebe:ZeebeServiceTask的定义中,并没有体现出具有IoMapping属性的配置,此时我们可以查询 zeebeServiceTask 定义中的 extend 中的所有元素类型定义,看看有没有 IoMapping 配置。


当然:结果是没有找到


那么此时这个 IoMapping 属性该怎么配置到serviceTask节点上呢?


嗯~~~ 经过之前研究了一番他们的属性面板,发现这种情况下默认会挂载到 extensionElements 属性中,所以假设我们为一个ServiceTask节点添加了一个 IoMapping 配置的话,此时该节点的 businessObject 会变成这样:


// 只是提示内容格式,不要真的这么赋值哈
serviceTask.businessObject = {
    extensionElements: {
        $type: "bpmn:ExtensionElements",
        values: [
            {
                $type: "zeebe:IoMapping",
                inputParameters: [],
                outputParameters: []
            }
        ]
    }
}


在 xml 中体现为:


<bpmn:serviceTask id="Activity_0py009y">
  <bpmn:extensionElements>
    <zeebe:ioMapping></zeebe:ioMapping>
  </bpmn:extensionElements>
</bpmn:serviceTask>


1.3 Input 与 Output


现在我们在回过头来看一下 IoMapping 的两个 properties 属性配置,其参数配置都是自定义类型,一个是Input,一个是Output


而在上面的 JSON Schema 文件中Input 和 Output 都是继承的 InputOutputParameter 类型,具有两个 字符串格式 的参数 source 与 target

但是因为在 JSON Schema 文件中已经对 InputOutputParameter 重新定义成了两个类型 Input 与 Output,并且在 IoMapping 的定义中也没有使用 InputOutputParameter,所以我们在编写 js 代码的时候也要注意moddle.create 时传入的参数必须是 properties 配置中定义的那个类型名


那么此时我们给 IoMapping 的 inputParameters 与 outputParameters 设置值时,可以这么操作:


const moddle = modeler.get('moddle')
const input1 = moddle.create('zeebe:Input', {source: '=xxx1', target: 'target1'})
const input2 = moddle.create('zeebe:Input', {source: '=xxx2', target: 'target2'})
const output1 = moddle.create('zeebe:Output', {source: '=xxx3', target: 'target3'})
const ioMapping = moddle.create('zeebe:IoMapping', 
    {
        inputParameters: [input1, input2],
        outputParameters: [output1]
    }
)
// 需要根据情况判断 extensionElements 的存在情况,这里只是演示就不判断了,直接更新
modeling.updateModdleProperties(element, extensionElements,
    { values: [...extensionElements.get("values"), ioMapping] }
);


此时我们会得到一个类似这样的 xml


<bpmn:serviceTask id="Activity_0py009y">
  <bpmn:extensionElements>
    <zeebe:ioMapping>
      <zeebe:input source="=xxx1" target="InputVariable_3mqm1gd" />
      <zeebe:input source="=xxx2" target="InputVariable_3mqm1gd" />
      <zeebe:output source="=xxx3" target="OutputVariable_01h6ldb" />
    </zeebe:ioMapping>
  </bpmn:extensionElements>
  <bpmn:incoming>Flow_0nx7hug</bpmn:incoming>
</bpmn:serviceTask>


这里说明一下, xml 是通过官方的编辑器生成的,所以 target 字段会默认生成一个类似 hashID 的值;在实际项目中也可以参考这部分


最后


到此,通过 JSON Schema 分析元素属性结构的过程就基本结束了。总的来说,虽然可以通过这样的方式去分析出来,但是依旧没有通过到导入一个 xml 直接打印属性结构来的快。只是增加一个这样的分析过程,能加深我们对这个 JSON Schema 配置的理解,在后面需要配置和定义项目特殊的属性的时候,也能更加快速的配置出来。


目录
相关文章
|
2天前
|
JSON 数据格式 开发者
什么是 JSON 文件的 Schema
什么是 JSON 文件的 Schema
103 0
|
2天前
|
编解码 JavaScript 前端开发
TypeScript【第三方声明文件、自定义声明文件、tsconfig.json文件简介、tsconfig.json 文件结构与配置】(六)-全面详解(学习总结---从入门到深化)
TypeScript【第三方声明文件、自定义声明文件、tsconfig.json文件简介、tsconfig.json 文件结构与配置】(六)-全面详解(学习总结---从入门到深化)
75 0
|
9月前
|
存储 缓存 数据可视化
(七)解析Streamlit的数据元素:探索st.dataframe、st.data_editor、st.column_config、st.table、st.metric和st.json的神奇之处(上)
(七)解析Streamlit的数据元素:探索st.dataframe、st.data_editor、st.column_config、st.table、st.metric和st.json的神奇之处
2496 0
|
2天前
|
JSON JavaScript 数据格式
【深入探究C++ JSON库】解析JSON元素的层级管理与遍历手段
【深入探究C++ JSON库】解析JSON元素的层级管理与遍历手段
146 2
|
2天前
|
XML 存储 JSON
C# | 使用Json序列化对象时忽略只读的属性
将对象序列化成为Json字符串是一个使用频率非常高的功能。Json格式具有很高的可读性,同时相较于XML更节省空间。 在开发过程中经常会遇到需要保存配置的场景,比如将配置信息保存在配置类型的实例中,再将这个对象序列化成为Json字符串并保存。当需要加载配置时,则是读取Json格式的字符串再将其还原成配置对象。在序列化的过程中,默认会将所有公开的属性和字段都序列化进入Json字符串中,这其中也会包含只读的属性或字段,而只读的属性和字段在反序列化的过程中其实是无意义的,也就是说这一部分存储是多余的。 本文将讲解如何在执行Json序列化时,忽略掉那些只读的属性和字段。
63 0
C# | 使用Json序列化对象时忽略只读的属性
|
7月前
|
JSON JavaScript 前端开发
37jqGrid 数据结构 - JSON结构
37jqGrid 数据结构 - JSON结构
33 0
|
8月前
|
XML 数据格式
SAP UI5 应用 manifest.json 文件里 Routes 数组元素的相对顺序,不可忽视的试读版
SAP UI5 应用 manifest.json 文件里 Routes 数组元素的相对顺序,不可忽视的试读版
50 0
|
8月前
|
JSON 前端开发 Java
springboot中自定义JavaBean返回的json对象属性名称大写变小写问题
springboot中自定义JavaBean返回的json对象属性名称大写变小写问题
120 0
|
9月前
|
JSON 前端开发 数据格式
前端——向json中添加或删除对象、属性
前端——向json中添加或删除对象、属性
|
9月前
|
存储 NoSQL UED
(七)解析Streamlit的数据元素:探索st.dataframe、st.data_editor、st.column_config、st.table、st.metric和st.json的神奇之处(中)
(七)解析Streamlit的数据元素:探索st.dataframe、st.data_editor、st.column_config、st.table、st.metric和st.json的神奇之处
587 0

热门文章

最新文章