将Nashorn中的JSON对象放入并获取到MongoDB

时间:2016-03-13 05:49:10

标签: java nashorn

我想在MongoDB中存储在Nashorn中运行的js脚本中的JSON对象,然后再将它们取回。 提供的API函数如下所示:

db.put("key", {"mykey":[1,2,3]})
var result = db.get("key")

我不知道如何处理它们有两个问题:

  1. 在Java端,我得到一个实现Map的ScriptObjectMirror。因此,如果有一个带有数组的JSON-Object,它已经在这里被破坏了。  例如{"key":[1,2,3]} -> {"key": {"0":1, "1":2, "2": 3}}
  2. 从DB读取JSON对象时,无法JSON.stringify该对象。它只返回undefined。没有任何可能性将Java中的JSON对象注入Nashorn,以便与JSON.stringify?兼容
  3. 您对我的问题有什么建议吗? 感谢

3 个答案:

答案 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
    }

}

来自柏林的亲切问候,伯纳德