Can a YAML value string be evaluated in Java?

Tags: , ,



Is it possible to pass Java code as a value in a YAML file. For example, something like this:

--- 
 dueDate: "DueDateCalc()"

DueDateCalc() might be a method defined in the Java code that is parsing the YAML. It would then set the Java dueDate property to the return of the predefined DueDateCalc() method.

Answer

This is possible within the constraints of Java runtime reflection, however you need to implement it yourself.

For example, your YAML could look like this:

--- 
dueDate: !call DueDateCalc

!call is a local tag for telling the loading code that the scalar value DueDateCalc should be interpreted as method to be called (this is chosen by you, not something predefined). You can implement this with a custom constructor for the !calc tag that searches for a method with the given name within some given class, and then calls it on some given object.

What about parameters? Well, still possible, but will get ugly fast. First problem is how you define the paramaters:

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

The former option lets YAML parse the parameters and you’ll get a list; the latter option requires you to parse the method call yourself from the string you get from YAML.

The second problem is to load the values into Java variables so that you can give them as argument list. Java reflection lets you get the method’s parameter types and you can use those to load the parameter values. For example, if the first parameter’s type is a String, you would parse 1 as a "1", while if it’s an int, you can parse 1 as int. This is possible with SnakeYAML’s builtin facilities if you’re using nested YAML sequences for method call encoding.

This would even work if parameters are class objects with complex structure, you’d just use normal YAML syntax and the objects will be loaded properly. Referring to variables in your code is not directly possible, but you could define another tag !lookup which retrieves values from a given Map structure.

While reflection lets you make method calls, you can not directly evaluate an expression like 6*9. So before you try and implement anything, evaluate which functionality you need and check whether it’s doable via reflection.



Source: stackoverflow