我想在MongoDB中存储在Nashorn中运行的js脚本中的JSON对象,然后再将它们取回。 提供的API函数如下所示:
db.put("key", {"mykey":[1,2,3]})
var result = db.get("key")
我不知道如何处理它们有两个问题:
{"key":[1,2,3]} -> {"key": {"0":1, "1":2, "2": 3}}
JSON.stringify
该对象。它只返回undefined。没有任何可能性将Java中的JSON对象注入Nashorn,以便与JSON.stringify?
兼容您对我的问题有什么建议吗? 感谢
答案 0 :(得分:2)
从JS中,您可以使用var jsonResult = Java.asJSONCompatible(result)
获取自定义包装器,其中JS Arrays作为Java列表公开。
从Java,您可以使用ScriptObjectMirror.wrapAsJSONCompatible(obj)
。
希望有所帮助。
答案 1 :(得分:0)
您的第一个解决方案,从JS到Java,按预期工作。问题是我们正在为其他开发人员提供API,我们不想告诉他们在JS-Code中使用Java.asJSONCompatible。
我无法获得从Java到JS的第二个解决方案。 这是我的测试:
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.junit.Assert;
import org.junit.Test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NashornJsonConversionTest {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn");
private class MyJsonWrapper extends HashMap<String, Object>{
}
@Test
public void shouldStringifyCorrectly() throws ScriptException {
String exepectedStringified = "{\"value\":1}";
MyJsonWrapper myJsonWrapper = new MyJsonWrapper();
myJsonWrapper.put("value", 1);
scriptEngine.put("jsonObject", ScriptObjectMirror.wrapAsJSONCompatible(myJsonWrapper, null));
Assert.assertEquals(1, scriptEngine.eval("jsonObject.value"));
String result = (String) scriptEngine.eval("JSON.stringify(jsonObject)");
Assert.assertEquals(exepectedStringified, result);
//Expected :{"value":1}
//Actual :null
}
@Test
public void shouldGetJSONWithArrayAsList() throws ScriptException {
Map<String, Object> result = (Map<String, Object>) scriptEngine.eval("Java.asJSONCompatible({value:[1,2,3]})");
List<Integer> values = (List<Integer>) result.get("value");
Assert.assertEquals(values.size(), 3);
// works as expected
}
}
答案 2 :(得分:0)
你必须将对象转换为nashorn中的“普通”对象。目前,您的脚本引擎会看到镜像。
这是一个jsfiddle:http://jsfiddle.net/Bernicc/00g6acp1/
/**
* This function convert an object coming from nashorn to a plain object.
* Instead of using <code>JSON.parse(value);</code> this method does only create new instances for objects.
* There is no need to parse a number, string or boolean.
*
* @param value the object which should be returned as clean object
* @returns {Object} the clean object
*/
toCleanObject: function (value) {
switch (typeof value) {
case "object":
var ret = {};
for (var key in value) {
ret[key] = this.toCleanObject(value[key]);
}
return ret;
default: //number, string, boolean, null, undefined
return value;
}
}
以上是您使用缩小版功能的测试。对于此示例,wrapAsJSONCompatible不是必需的。
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.junit.Assert;
import org.junit.Test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NashornJsonConversionTest {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn");
private class MyJsonWrapper extends HashMap<String, Object>{
}
@Test
public void shouldStringifyCorrectly() throws ScriptException {
String exepectedStringified = "{\"value\":1}";
MyJsonWrapper myJsonWrapper = new MyJsonWrapper();
myJsonWrapper.put("value", 1);
// for this example wrapAsJSONCompatible is not necessary
//scriptEngine.put("jsonObject", ScriptObjectMirror.wrapAsJSONCompatible(myJsonWrapper, null));
scriptEngine.put("jsonObject", myJsonWrapper);
scriptEngine.eval("function toCleanObject(t){switch(typeof t){case\"object\":var e={};for(var n in t)e[n]=toCleanObject(t[n]);return e;default:return t}}");
scriptEngine.eval("jsonObject = toCleanObject(jsonObject);");
Assert.assertEquals(1, scriptEngine.eval("jsonObject.value"));
String result = (String) scriptEngine.eval("JSON.stringify(jsonObject)");
Assert.assertEquals(exepectedStringified, result);
//Expected :{"value":1}
//Actual :null
}
@Test
public void shouldGetJSONWithArrayAsList() throws ScriptException {
Map<String, Object> result = (Map<String, Object>) scriptEngine.eval("Java.asJSONCompatible({value:[1,2,3]})");
List<Integer> values = (List<Integer>) result.get("value");
Assert.assertEquals(values.size(), 3);
// works as expected
}
}
来自柏林的亲切问候,伯纳德