可以在 Java 中评估 YAML 值字符串吗?

Can a YAML value string be evaluated in Java?

是否可以将 Java 代码作为 YAML 文件中的值传递。例如,像这样:

--- 
 dueDate: "DueDateCalc()"

DueDateCalc() 可能是在解析 YAML 的 Java 代码中定义的方法。然后它将 Java dueDate 属性 设置为预定义 DueDateCalc() 方法的 return。

这在 Java 运行时反射的约束下是可能的,但是您需要自己实现它。

例如,您的 YAML 可能如下所示:

--- 
dueDate: !call DueDateCalc

!call 是一个局部标签,用于告诉加载代码标量值 DueDateCalc 应该被解释为要调用的方法(这是由您选择的,而不是预定义的)。您可以使用 !calc 标记的自定义构造函数来实现此功能,该标记在某个给定的 class 中搜索具有给定名称的方法,然后在某个给定的对象上调用它。

参数呢?好吧,仍然有可能,但会很快变得丑陋。第一个问题是如何定义参数:

with nested YAML sequences: !call [MyMethod, [1, 2, 3]]
with a scalar that needs to be parsed: !call MyMethod(1, 2, 3)

前一个选项让 YAML 解析参数,你会得到一个列表;后一个选项要求您自己从从 YAML 获得的字符串中解析方法调用。

第二个问题是将值加载到 Java 变量中,以便您可以将它们作为参数列表提供。 Java 反射让您可以获取方法的参数类型,您可以使用它们来加载参数值。例如,如果第一个参数的类型是 String,则可以将 1 解析为 "1",而如果是 int,则可以将 1 解析为 int。如果您使用嵌套的 YAML 序列进行方法调用编码,这可以通过 SnakeYAML 的内置工具实现。

如果参数是 class 具有复杂结构的对象,这甚至会起作用,您只需使用普通的 YAML 语法,对象就会被正确加载。在您的代码中引用变量是不可能的,但您可以定义另一个标记 !lookup,它从给定的 Map 结构中检索值。

虽然反射允许您进行方法调用,但您不能直接计算 6*9 这样的表达式。因此,在您尝试实现任何东西之前,请先评估您需要哪些功能,并通过反射检查它是否可行。