flowable expression和json字符串中的双引号内容

Flowable 6.6.0 BPMN用户指南 - (3) The Flowable API - 3.6 表达式(Expressions) 3.6 表达式(Expressions) Flowable uses UEL for expression-resolving. UEL stands for Unified Expression Language and is part of the EE6 specification (see the EE6 specification for detailed information). Expressions can be used in, for example, Java Service tas 阅读详情

前言

最近做项目,发现了一批特殊的数据,即特殊字符",本身输入双引号也不是什么特殊的字符,毕竟在存储时就是正常字符,只不过在编码的时候需要转义,转义符是\,然而转义符\也是特殊字符,又需要转义。这就造成了json字符串如果需要",需要很可能转义2次,即\\ \"。一般而言单层"只需要转义一次即可,但是json很可能再次嵌套,所以有时候需要多次转义,这里的\转义符在字符串也是有特殊含义的,毕竟内存存储"并不需要转义,这就出现了平时极难理解的情况。

这些其实还是比较好理解的,即:jvm内存的存储"并没有转义符,只不过编码需要,json字符串需要,负责json序列化和反序列化过程就是不可逆的。比如只能序列化,不能反序列化,但是如果Java执行groovy,或者执行了一些express表达式呢,这些数据会发生变化吗。

准备

准备demo,随意写一个对象,并且写一个groovy和express示例。

    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>3.0.23</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.52</version>
        </dependency>
    </dependencies>

然后写一个groovy脚本

package org.example

def demo = binding.getVariable("demoBean")
println(demo.name)
demo.name = "demo"
demo.no = "000"
println(demo.name)

写一个bean(自行实现-忽略,普通javabean)和main测试类

public class Main {
    public static void main(String[] args) throws IOException {
        TestBean testBean = new TestBean();
        testBean.setNo("1213");
        testBean.setName("haha\"");
        Binding binding = new Binding();
        binding.setVariable("demoBean", testBean);
        GroovyShell groovyShell = new GroovyShell(binding);


        System.out.println("1. " + JSON.toJSONString(testBean));
        groovyShell.evaluate(new File("/Users/huahua/IdeaProjects/groovy-demo/src/main/java/org/example/demo.groovy"));

        Object object = groovyShell.getVariable("demoBean");
        System.out.println("2. " + JSON.toJSONString(object));

    }
}

这里要注意,Java执行groovyshell,需要的绑定关系是 new GroovyShell(binding),这里的binding命令会自动传递到groovy脚本,执行后如下

json

如上的结果分析:这里的json实际上有转义符,就说明了可读取的json实际上是解释形态,并不是编译运行形态,因为运行态的字符串实际上存放在常量池,是有转义符的,通过javap看看main类

javap -c -p -v Main.class 

但是如果字符串存入内存中,即运行态,并没有转义符,这就触发了问题的来源,json需要转义符,严格说是解释态需要,但是内存不需要,在传递的过程很可能出现丢失转义符导致json反序列化失败,因为json自身会对" { } 这些自身字符进行转义以区分是json字符串还是内容字符串,然而字符串的解释也需要,那就会出现再次转义的情况。

但是内存存储没有字符串的转义的说法,存储的原始信息

Grooovy脚本

笔者开始认为groovy脚本的操作可能会丢失\",如示例,因为实际生产有执行groovy,但是因为是内存操作,内存本身就没有转义符\

注释掉groovy对name的操作,可以看到实际上并没有任何变化,jvm内存本身就是没有转义符存储的,此时name字符串仅仅是对象的属性

json序列化后字符串

证明跟原始的数据没区别,转json后转义符\没丢失

express

后来发现对象经过了类似spring的@Value这样的表达式格式化后,出现了转义符丢失,毕竟javabean的值不是固定不变的,设置表达式,会在各个流程中进行格式化具体的表达式,从而动态的执行不同的参数和返回,计算本质就是输入 计算 输出。

模拟一个示例:最常见的就是工作流,在值传递时,实际上规则引擎,spring等都有express的能力,就以工作流为例bpmn2.0的expression

        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-engine-common</artifactId>
            <version>6.5.0</version>
        </dependency>

编写测试代码

public class Main {
    public static void main(String[] args) throws IOException {
        TestBean testBean = new TestBean();
        testBean.setNo("1213");
        testBean.setName("haha\"");

        Map<String, Object> map = new HashMap<>();
        map.put("testBean", testBean);
        map.put("testBean.name", "haha\"");
        map.put("testBean.no", testBean.getNo());

        ExpressionManager expressionManager = new DefaultExpressionManager();
        Expression expression = expressionManager.createExpression("{\"name\":\"${testBean.name}\",\"no\":\"${testBean.no}\"}");
        Object obj = expression.getValue(new VariableContainerWrapper(map));
        System.out.println(obj);
    }
}

然后执行

可以看到转义符消失,原因实际上已经很明确了express是表达式替换,并不是类似json的解释性格式,jvm内存是没有转义符的,Java本质上是解释性语言,所以class文件有转义符,所以"前的\转义符丢失,如果把这个json送给json反序列化一定报错,识别不了内容双引号的含义。

原因分析

org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstComposite

其实是在这个示例中,使用字符串拼接的方式执行了替换,内存并没有相关的转义符,这里使用了bean的解析器,毕竟数据是从Javabean获取的

	public Object eval(Bindings bindings, ELContext context) {
		StringBuilder b = new StringBuilder(16);
		for (int i = 0; i < getCardinality(); i++) {
			b.append(bindings.convert(nodes.get(i).eval(bindings, context), String.class));
		}
		return b.toString();
	}

然后解析器实际上有多种

    public Object getValue(ELContext context, Object base, Object property) {
		context.setPropertyResolved(false);
		for (int i = 0, l = resolvers.size(); i < l; i++) {
			Object value = resolvers.get(i).getValue(context, base, property);
			if (context.isPropertyResolved()) {
				return value;
			}
		}
		return null;
	}

如果使用json解析器,那么是不是可以正常呢

 

看看json解析器的判断

懵,果然可以,但是这仅支持jackson,来试一下,确实可以了,但是结果依旧

public class Main {

    private static ObjectMapper reader = new ObjectMapper();

    public static void main(String[] args) throws IOException {
        TestBean testBean = new TestBean();
        testBean.setNo("1213");
        testBean.setName("haha\"");

        Map<String, Object> map = new HashMap<>();
        JsonNode jsonNode = reader.readTree("{\"name\":\"haha\\\"\",\"no\":\"1213\"}");
        map.put("testBean", jsonNode);
        map.put("testBean.name", "haha\"");
        map.put("testBean.no", testBean.getNo());

        ExpressionManager expressionManager = new DefaultExpressionManager();
        Expression expression = expressionManager.createExpression("{\"name\":\"${testBean.name}\",\"no\":\"${testBean.no}\"}");
        Object obj = expression.getValue(new VariableContainerWrapper(map));
        System.out.println(obj);
    }
}

看看结果 

根源还是因为express在flowable的工具类中是字符串拼接,且本身是字符串 

所以仅仅是支持了不同的输入对象逻辑罢了,最终结果并不会有任何变化

总结

通过示例可以看到字符串包括json需要对字符串的"内容进行转义,包括代码编写,class文件,但是jvm内存是不认"的转义符的,存储的就是真实的值,不存在转义的说法,而类似groovy脚本这样的类class语言实际上也是如此,毕竟操作在内存操作,class虚拟机不会有任何不同,毕竟class不一定能反编译Java,但是Java一定是编译为class,所以groovy并不会影响值操作的"结果。

关键点,我们会经常使用expression,不一定是工作流,以flowable为例,flowable支持各种输入传入,表达式也是标准的,但是expression的结果是字符串拼接的,不会考虑解释态,类似json这样的格式,所以输出的结果会丢弃转义符(实际上在字符串载入内存就丢弃了),expression仅仅是真实的还原内存数据,但是这确不是我们特定场景需要的结果,如果传给json反序列化bean就会报错。

Flowable源码注释(七十四)案例任务活动行为 Flowable-6.7.2 源码注释地址:https://github.com/solojin/flowable-6.7.2-annotated CaseTaskActivityBehavior 案例任务活动行为 /** * 案例任务活动行为 * 使用案例服务任务启动CMMN案例 * * @author Tijs Rademakers * @author Joram Barrez */ public class CaseTaskActivityBehavior extends Abstract 阅读详情

相关推荐

flowable 6.4.2 - 多实例(与签、或签的实现机制)

▷ 创建Behavior( SequentialMultiInstanceBehavior、ParallelMultiInstanceBehavior) ``` // org.flowable.engine.impl.bpmn.parser.handler.UserTaskParseHandler#parse(org.flowable.engine.impl.bpmn.parser.BpmnParse, org.flowable.bpmn.model.BaseElement) class UserTa

~~简~~ 5456

Flowable源码注释(五十九)抽象行为工厂类

Flowable-6.7.2 源码注释地址:https://github.com/solojin/flowable-6.7.2-annotated AbstractBehaviorFactory 抽象行为工厂类 内部持有表达式管理器,主要负责将FieldExtension类型的集合转化为FieldDeclaration类型的集合 package org.flowable.engine.impl.bpmn.parser.factory; import java.util.ArrayList; import

jinyangjie的博客 385

Flowable 6.6.0 BPMN用户指南 - (3) The Flowable API - 3.7 表达式函数(Expression functions)

3.7 表达式函数(Expression functions) [Experimental] Expression functions have been added in version 6.4.0. To make working with process variables easier, a set of out-of-the-box functions is available, under the variables namespace. [实验性]6.4.0版中添加了表达式函数。 为了更容易处

月满闲庭的博客 1974

Flowable进阶学习(四)任务分配与流程变量

flowable的任务分配方式,包括固定分配,表达式分配,监听器分配。 其中表达式分配包括值表达式和方法表达式。 流程变量包括全局变量和局部变量。其中局部变量在任务完成时会被删除。全局变量要在流程实例结束后才会被删除。 图解流程实例的关系。

Huathy的博客 3701

Flowable 6.6.0 BPMN用户指南 - (4)Spring集成 - 4.3 表达式(Expressions)

4.3 表达式(Expressions) When using the ProcessEngineFactoryBean, all expressions in the BPMN processes will also ‘see’ all the Spring beans, by default. It’s possible to limit the beans (even none) you want to expose in expressions using a map that you can co

月满闲庭的博客 1275

bpmn-js 流程设计器 与 flowable/activiti 拓展的可行性研究

bpmn-js 流程设计器 与 flowable/activiti 拓展的可行性研究前因先上效果图涉及技术引用 前因 最近在准备开源一款流程引擎项目,主要包含 流程设计器 表单设计器 流程引擎,碰见了一个问题 开发过程中 经常需要拓展节点或节点元素,因为bpmn规范可能不满足实际项目需求。记录一下 解决思路。 先上效果图 涉及技术 前端使用 bpmn.js 拓展 flowable.json或者 activiti.json,新增我们 拓展的节点及元素。 { "name": "Flowable",

zhuzhoulin的博客 9427

flowable 服务任务 类,表达式,委托表达式(代理表达式)

讲解flowable中serviceTask的类,表达式,代理表达式的用法

CCCout的博客 6712

Matplotlib图片尺寸调整全攻略:从figsize到savefig的实战技巧

在数据可视化与科学计算中,图形尺寸控制是影响图表可读性与专业度的基础环节。其核心原理在于协调逻辑尺寸(英寸)与物理输出(像素)的映射关系,这直接决定了信息呈现的清晰度与布局合理性。从技术价值看,精准的尺寸控制能提升图表在不同媒介(如学术论文、报告、网页)中的适配性,避免显示不全、模糊失真等常见问题。在应用场景上,无论是Jupyter Notebook中的交互探索、自动化报告的批量生成,还是满足严格出版要求的插图制作,都需要掌握对应的尺寸调整策略。本文聚焦于matplotlib中的figsize参数、rcPa

weixin_30899023的博客 327

Flowable工作流 实现多实例任务(会签或签)

Flowable 多实例 会签:${nrOfCompletedInstances==nrOfInstances}或签:${nrOfCompletedInstances>=1}固定集合、变量参数为approverList、approver。

telescopewang的博客 6458

Accelstepper 库中的参数计算公式

要完全调试电机的各个参数,例如最大速度,加速度等,就需要了解其计算公式和原理。 以下是代码注释: /// This code uses speed calculations as described in /// "Generate stepper-motor speed profiles in real time" by David Austin/// http://fab.cba.mi...

wenguitao的博客 4454

InVEST模型实战指南:从水源涵养到热岛缓解的生态系统服务评估

本文提供了InVEST模型的实战指南,详细介绍了从环境搭建、数据预处理到核心模型应用的完整流程。通过水源涵养、碳存储、土壤保持和城市热岛缓解等核心模型的拆解,帮助生态学者与规划者系统量化评估生态系统服务,将复杂的生态价值转化为直观的空间数据与地图,为科学决策提供有力支撑。

weixin_29197051的博客 427

flowable工作流学习笔记

这里写目录标题一级目录二级目录三级目录什么是BPMNFlowable简介Activiti 中的 Start event(启动事件元素)介绍Activiti中的activiti:expression和activiti:delegateExpression有什么区别?会签和或签的概念多实例实现会签功能Flowable-BPMN操作流程部署启动方案设计 一级目录 二级目录 三级目录 什么是BPMN BPMN定义了一个业务流程图(Business Process Diagram),该业务流程图基于一个流程图(flo

ZWL2333的博客 3646

python爬取《你好, 李焕英》豆瓣评论数据

# 导入工具包 import requests from bs4 import BeautifulSoup import time import pandas as pd import numpy as np # 请求头 headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'} # =

python技巧分享 3454

Flowable入门系列文章15 - 整合Spring 02

flowable入门、flowable现状、flowable开源产品、flwoable入门系列、flowable课程、flowable与activiti区别 Flowable是用Java编写的轻量级业务流程引擎。Flowable流程引擎允许您部署BPMN 2.0流程定义(用于定义流程的行业XML标准),创建 流程定义的流程实例,运行查询,访问活动或历史流程实例以及相关数据等等。本节将逐步介绍各种概念和API,通过您可以在自己的开发 机器上进行的实例进行实现。

分享牛 667

H3C无线控制器AC与第三方认证系统集成实现企业级Portal短信认证方案

本文详细阐述了如何将H3C无线控制器(AC)与第三方认证系统集成,构建企业级Portal短信认证方案。该方案通过手机号作为临时凭证,实现了访客网络的实名追溯、权限控制与专业体验。文章深入解析了方案原理、H3C AC的关键配置步骤、第三方系统对接要点及短信网关选型避坑指南,为企业提升网络安全管理与访客服务质量提供了完整、可行的实战指导。

a3b4c5的博客 193

CESM笔记——CESM1.0-CESM1.2.2-CESM2.1.3三个版本模式工作流对比

最近测试了CESM1.0,CESM1.2.2和CESM2.1.3三个版本,不同版本在workflow上有一些区别,来做点笔记。 CESM1.0 测试compset:B_2000,F_2000 workflow: 1. create_newcase -case ~/CESM/cesm1_0/script/B_2000 -compset B_2000 -res f19_g16 -mach tianhe 2. cd B_2000 (optional) env_mach_pes.xml ##修改核数,

砍柴姑娘Jourosy的博客 4941

BPMNJS节点实现扩展flowable标签--

二、导入创建的flowable.json 文件。第一:创建flowable.json文件。注:此文主要是自用,能帮到大家更好。

qq_36619440的博客 991

攻防世界 web高手进阶区 9分题 Web_python_flask_sql_injection

继续ctf的旅程,开始攻防世界web高手进阶区的9分题,本文是Web_python_flask_sql_injection的writeup

闵行小鱼塘 1470

(4)Flowable任务分配-固定分配、表达式分配、监听器分配

固定分配、表达式分配、监听器分配

bluede2015的博客 1985

C#上位机+YOLO实战:从环境搭建到实现首个目标检测(零基础入门)

/ YOLOv8的类别名称(共80类,对应COCO数据集)// ONNX推理会话// YOLOv8的输入宽度// YOLOv8的输入高度本文从技术选型、环境搭建到代码实现,详细介绍了如何将C#上位机与YOLOv8结合,实现基础的目标检测功能。整个过程避开了常见的坑点,同时对核心原理和代码逻辑进行了详细解析,希望能帮助零基础的开发者快速入门。实际上,C#上位机+YOLO的组合在工业领域有非常广泛的应用,本文的案例只是一个起点。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 790

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【Flowable】Flowable任务分配和流程变量

【Flowable】Flowable任务分配和流程变量

qq_41466440的博客 2893

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Flowable 后端表达式详解:动态流程控制的核心引擎

Flowable后端表达式系统是流程动态控制的核心组件,基于UEL提供强大的逻辑处理能力。文章深入解析了其技术架构,包括表达式解析器、JUEL引擎和变量解析机制。核心表达式类型分为值表达式和方法表达式,支持流程变量获取和Java方法调用。系统提供丰富的上下文变量如execution、task和runtimeService等。高级技巧涵盖复杂条件、集合操作和日期处理表达式,以及安全实践如权限控制和数据脱敏。文章还介绍了自定义函数扩展方法、性能优化策略(预编译和缓存)以及调试技巧。这套表达式系统为业务流程提供了

csdn_tom_168的博客 1353

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Flowable入门系列文章13 - Flowable API 03

flowable入门、flowable现状、flowable开源产品、flwoable入门系列、flowable课程、flowable与activiti区别 Flowable是用Java编写的轻量级业务流程引擎。Flowable流程引擎允许您部署BPMN 2.0流程定义(用于定义流程的行业XML标准),创建 流程定义的流程实例,运行查询,访问活动或历史流程实例以及相关数据等等。本节将逐步介绍各种概念和API,通过您可以在自己的开发 机器上进行的实例进行实现。

分享牛 1082

flowable任务分配方式篇动态部门经理:固定分配、表达式分配、监听器分配

flowable 动态指定部门经理

nalanxiaoxiao2011的博客 4654

Flowable入门系列文章132 - 任务 06

flowable入门、flowable现状、flowable开源产品、flwoable入门系列、flowable课程、flowable与activiti区别Flowable是用Java编写的轻量级业务流程引擎。 Flowable流程引擎允许您部署BPMN 2.0流程定义(用于定义流程的行业XML标准),创建流程定义的流程实例,运行查询,访问活动或历史流程实例以及相关数据等等。本节将逐步介绍各种概念和API,通过您可以在自己的开发机器上进行的实例进行实现。

分享牛 658

flowable节点属性扩展

在工作中,有些工作需求flowable自带的节点属性并不能满足,就需要添加一些自定义的节点属性 对于上面就是实际项目中的效果,那么如何做呢? 1、修改bpmnjson的数据 { “name”: “nodetypepackage”, “properties”: [ { “id”: “nodetype”, “type”: “dragon-nodetype-combobox”, “title”: “节点...

分享牛 1万+
上一篇: springboot kafka在kafka server AUTH变动后consumer自动销毁
下一篇: kafka 3.5.0 raft协议安装
fenglllle
博客等级 码龄8年 461粉丝 242原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值