You need to enable JavaScript to run this app. 如何实现支持Ruby变量与对象插值的用户自定义Webhook JSON动态模板
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持Ruby变量与对象插值的用户自定义Webhook JSON动态模板

问题核心根源

当前用String#%输出不符合预期,本质是执行流程的顺序错位:

  • String#%是纯文本层面的替换逻辑,无论占位符对应的原始值是什么类型,都会强制调用to_s转成普通字符串
  • 现有流程是先在纯字符串层面完成所有占位符替换,再把替换完的字符串转成JSON。此时所有嵌套对象早已经被转成Ruby语法格式的字符串,自然没法输出结构化的嵌套JSON节点。
可行实现方案

1. 结构化模板替换(最稳定、无安全风险)

完全绕开“先把全模板当字符串替换、再转JSON”的思路,把用户提交的模板当成和最终输出同结构的JSON/YAML数据,做递归遍历替换:

  • 规则设计:沿用大家熟悉的%{key}或者{{key}}占位符格式,直接把占位符作为模板节点的值,不强制把占位符包裹成纯字符串值
  • 遍历逻辑:
    • 碰到普通节点值时,先判断这个值是不是“纯占位符”(也就是整个字符串就是占位符标记,没有其他额外文本)
    • 如果是纯占位符,直接把变量上下文里对应key的原始结构化对象塞到这个节点的位置,不做任何字符串转换
    • 如果占位符只是字符串的一部分(比如"用户%{username} 的反馈已收到"),就对这个字符串做常规的文本替换,生成普通字符串值
    • 如果碰到嵌套的哈希、数组结构,就递归执行上面的判断逻辑

举个实际的模板示例:

{
  "id": "%{id}",
  "message": "%{message}",
  "badge": "%{badge}"
}

替换时,因为%{badge}是纯占位符,会直接把badge对应的嵌套结构化对象放到对应位置,最终输出的JSON完全符合预期,不会出现字符串化的哈希内容。

这个方案的优势:

  • 无任何代码执行风险,整个流程只是固定规则的占位符匹配,完全不涉及用户提交内容的代码执行
  • 对嵌套结构的控制完全可控,什么时候输出结构化内容、什么时候输出文本,规则清晰没有歧义
  • 实现成本极低,递归遍历的逻辑几十行代码就能写完,不需要引入重型模板引擎

2. 兼容现有%{}语法的调整方案

如果不想换掉用户已经习惯的%{key}占位符格式,只需要调整执行顺序即可解决问题:

  • 不再先对整个模板字符串做String#%替换
  • 先把用户写的模板解析成Ruby原生的Hash/数组结构,再递归遍历每个节点做替换
  • 递归过程中碰到纯占位符的字符串值,直接取出对应原始值替换;碰到嵌在文本里的占位符,再调用String#%做文本拼接
  • 等整个结构全部替换完成后,最后统一调用to_json输出最终载荷

这个调整只要把原来“先替换、再转结构”的流程反过来,就能彻底解决嵌套对象被字符串化的问题。

不推荐的踩坑选项
  • ERB:虽然能实现动态替换,但允许执行任意Ruby代码,哪怕加沙箱限制也很容易被绕过,绝对不适合开放给外部用户自定义模板使用
  • RABL、Jsonnet这类方案:要么是面向服务端开发的固定模板,没法灵活支持用户自定义的动态结构;要么语法学习成本太高,普通用户很难快速上手写出符合要求的内容

内容的提问来源于stack exchange,提问作者Peter P.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 23:06:04