如何在WSO2 Stream Processor中使用含点号与@符号的属性?
确实,WSO2 Stream Processor(SP)的Siddhi语法默认不允许属性名包含@或.这类特殊字符——编辑器报错就是因为这个语法限制。不过有几个实用的解决方案可以绕过这个问题,核心思路是在事件进入正式流定义前,把带特殊字符的字段映射/转换为合法的属性名,下面结合你的例子详细说明:
方法1:输入源直接映射(最简便)
如果你的事件是通过HTTP、Kafka、MQTT等适配器传入的,可以直接在@source的@map配置里,把带特殊字符的原始字段映射成合法的属性名。这样流定义里只用合法名字,编辑器就不会报错了。
比如针对你给出的两个流需求,配置可以这么写:
-- 先定义合法属性名的目标流 define stream test (name string, eventTimestamp string); define stream test2 (corePct double, systemInfo string); -- 从HTTP接收带特殊字符的事件,映射到合法属性 @source(type='http', receiver.url='http://localhost:8006/test-input', @map(type='json', @attributes(name='name', eventTimestamp='@timestamp'))) define stream InputTestStream; @source(type='http', receiver.url='http://localhost:8006/test2-input', @map(type='json', @attributes(corePct='core.pct', systemInfo='system.info'))) define stream InputTest2Stream; -- 将映射后的事件转发到目标流 @info(name='Route-Test-Data') from InputTestStream select name, eventTimestamp insert into test; @info(name='Route-Test2-Data') from InputTest2Stream select corePct, systemInfo insert into test2;
这里的关键是@attributes里的映射规则:左边是流里的合法属性名,右边是原始事件里带特殊字符的字段名。
方法2:通过JSON解析转换(灵活适配复杂场景)
如果你的事件是整段JSON格式传入,也可以先把整个事件作为json类型的属性接收,再通过Siddhi的JSON解析语法提取字段,转换为合法属性名。这种方式适合字段较多或者需要动态处理的场景。
示例代码:
-- 先接收原始JSON事件 define stream RawInputStream (payload json); -- 解析JSON,提取带特殊字符的字段并映射为合法属性 @info(name='Transform-Special-Fields') from RawInputStream select payload.name as name, payload.`@timestamp` as eventTimestamp, -- 用反引号包裹带@的键 payload.`core.pct` as corePct, -- 用反引号包裹带点的键 payload.`system.info` as systemInfo insert into ProcessedStream; -- 后续就可以用ProcessedStream里的合法属性进行处理了 define stream test (name string, eventTimestamp string); define stream test2 (corePct double, systemInfo string); @info(name='Split-to-Target-Streams') from ProcessedStream select name, eventTimestamp insert into test; from ProcessedStream select corePct, systemInfo insert into test2;
注意:访问JSON中含特殊字符的键时,必须用反引号(`)包裹,否则Siddhi会解析出错。
方法3:适配器层面预处理(自定义场景)
如果是自定义适配器或者需要批量替换特殊字符,可以在适配器的处理逻辑里,把原始字段名中的@替换为_at_、.替换为_dot_这类合法字符,再传入流中。比如在自定义HTTP适配器的代码里,提前遍历JSON字段名做替换,这样流定义直接用替换后的名字即可。
关键提醒
Siddhi的属性名必须符合标识符规则:只能包含字母、数字、下划线,且不能以数字开头。所以永远不要在流定义里直接使用带@或.的属性名,必须通过上述映射/转换的方式提前处理。
内容的提问来源于stack exchange,提问作者bygre14790

