I use nashorn in my project. I want get property from a json, but property may not have value.
In javascript, use optional chaining and set a value, if property is null; but in nashorn, when I use (?.), I get this error:
import org.springframework.stereotype.Service
import javax.script.ScriptEngineManager
import javax.script.Bindings
@Service
class SampleService {
class Person(
val firstName: String,
val lastName: String,
val child: Child?
)
class Child(
val name: String,
val age: Int
)
fun runScript() {
val engine = ScriptEngineManager().getEngineByName("nashorn")
val bindings: Bindings = engine.createBindings()
val person = Person("John", "Smite", null)
bindings["person"] = person
try {
val script = """
var childAge = person.child?.age ?? 0;
childAge; //return as result.
""".trimIndent()
val scriptResult: Any = engine.eval(script, bindings)
} catch (e: Exception) {
throw e
}
}
}
I get this error:
javax.script.ScriptException: <eval>:1:28 Expected an operand but found .
var childAge = person.child?.age ?? 0;
^ in <eval> at line number 1 at column number 28
I checked this link, but I could not solve the problem: Optional chaining (?.)
How can I fix this error?
The current strategy for Nashorn is to follow the ECMAScript specification. When we release with JDK 8 we will be aligned with ECMAScript 5.1.link
The the Nashorn engine has been deprecated in JDK 11 as part of JEP 335 and is scheduled to be removed from future JDK releases as part of JEP 372.
GraalVM JavaScript can step in as a replacement for code previously executed on the Nashorn engine. It provides all the features previously provided by Nashorn, with many being available by default, some behind flags, some requiring minor modifications to your source code.link
Optional chaining is pretty new and ECMAScript 5.1 is not supported this feature.
I migrate from nashorn to GraalVM JavaScript and changed the code as follows:
import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine
import org.graalvm.polyglot.Context
import org.graalvm.polyglot.HostAccess
import org.springframework.stereotype.Service
import javax.script.ScriptEngine
@Service
class SampleService {
data class Person(
val firstName: String,
val lastName: String,
val child: Child?
)
data class Child(
val name: String,
val age: Int
)
fun runScript() {
val person = Person("John", "Smite", null)
val engine: ScriptEngine = GraalJSScriptEngine.create(null,
Context.newBuilder("js")
.allowHostAccess(HostAccess.ALL)
.allowExperimentalOptions(true)
.option("js.ecmascript-version", "2020")
.option("js.nashorn-compat", "true"))
engine.put("person", person)
try {
val script = """
print(person.child?.name);
//print undefined
print(person.child?.name ?? 'not exist');
//print not exist
""".trimIndent()
engine.eval(script)
} catch (e: Exception) {
throw e
}
}
}