如何将Rhino生成的JSON数据结构(Native Object)转换为Java数据结构?

时间:2015-03-19 02:22:02

标签: java json rhino

我正在尝试在JavaScript代码中生成数据结构,并处理来自Java(Java 6或7中的Rhino)的结果。

我成功地使用以下方法从Java调用JS函数:

Object result = invocableEngine.invokeFunction(functionName, parameters);

现在,在JS方面,该结果是一个JSON数据结构如下:

{ 
  "key1" : { "key1_1" : "value1_1", "key1_2" : 11 },

  "key2" : [ {  "key2_1": "foo2"
              , "key2_1" : "bar2" },

             {  "key2_1": "foo2"
              , "key2_1" : "bar2"
              , "key2_3" : [1,2,3] } ]
}

然而,在Java方面,"结果"是sun.org.mozilla.javascript.internal.NativeObject

类型的对象

我有没有办法将它转换为合理的Java数据结构,而没有将JSON序列化为字符串然后使用Gson解析它的开销?

假设目前数据结构的定义合理,例如: 我知道该对象是一个带键和#34; key1"和" key2",第一个映射到带有键" key1_1"的散列。和" key1_2&#34 ;;第二个映射到一个哈希数组,每个哈希都有键" key2_1"和" key2_2"这是标量和" key2_3"这是一个数组。

我的两个优先事项是:

  1. 表现(这是我对序列化+ Gson解析持谨慎态度的一个原因)
  2. Java 6,7和8之间的可移植性(但是,我更喜欢速度更快的非便携式解决方案)。

3 个答案:

答案 0 :(得分:1)

这是从NativeObject到JSONObject的代码。 我认为从NativeObject到Map都是相似的。

    public static JSONObject toJsonObject(NativeObject nativeObject)
    {
        JSONObject object = new JSONObject();
        Set<Entry<Object, Object>> entrySet = nativeObject.entrySet();
        for (Entry<Object, Object> entry : entrySet)
        {
            try
            {
                if (entry.getValue() instanceof String)
                {
                    object.put(entry.getKey().toString(), new JSONObject(entry.getValue().toString()));
                }
                else if (entry.getValue() instanceof NativeArray)
                {
                    object.put(entry.getKey().toString(), toJsonArray((NativeArray) entry.getValue()));
                }
                else if (entry.getValue() instanceof NativeObject)
                {
                    object.put(entry.getKey().toString(), toJsonObject((NativeObject) entry.getValue()));
                }
            }
            catch (JSONException e)
            {
                try
                {
                    object.put(entry.getKey().toString(), entry.getValue().toString());
                }
                catch (JSONException ignored)
                {
                }
            }
        }


        return object;
    }

    public static JSONArray toJsonArray(NativeArray nativeArray)
    {
        JSONArray array = new JSONArray();

        for (Object o : nativeArray)
        {
            if (o instanceof NativeObject)
            {
                array.put(toJsonObject((NativeObject) o));
            }
            else if (o instanceof NativeArray)
            {
                array.put(toJsonArray((NativeArray) o));
            }
            else
            {
                try
                {
                    array.put(new JSONObject(o.toString()));
                }
                catch (JSONException e)
                {
                    array.put(o.toString());
                }
            }
        }

        return array;
    }

答案 1 :(得分:0)

你可以解析任何json字符串&#34; object&#34;使用Gson将其解析为LinkedTreeMap,如下所示:

import com.google.gson.internal.LinkedTreeMap;

String json = <your raw json>
LinkedTreeMap map = new Gson().fromJson(json, LinkedTreeMap.class);

在解析您的示例输入后,以下是如何使用它的示例:

System.out.println(((List<LinkedTreeMap>)map.get("key2")).get(1).get("key2_3"));

输出:

[1.0, 2.0, 3.0]

事先知道结构是有帮助的,但并不重要,因为你可以在得到它时检查每个节点的类型。

至于性能,我创建了4个密钥的样本输入,每个密钥在列表中有400多个条目。在JVM警告之后,我的低规格旧笔记本电脑上的解析只用了2ms。

答案 2 :(得分:-1)

您可以从json内部构建java对象。

像这样的东西(我正在构建新的java.lang.String,但同样你可以构建自己的类):

java -jar js.jar
Rhino 1.7 release 5 2015 01 29
js> str=new java.lang.String("Hello world")
Hello world
js> java.lang.System.out.println(str)
Hello world