我正在尝试在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进行解析的开销?
目前假设数据结构定义合理,例如我知道对象是键为“ key1”和“ key2”的哈希,第一个映射为键为“ key1_1”和“ key1_2”的哈希;第二个映射到哈希数组,每个哈希都有标量的键“ key2_1”和“ key2_2”,而数组是“ key2_3”。
我的两个优先顺序是:
您可以通过将Gson
解析为LinkedTreeMap
来使用它解析任何json字符串“对象”,如下所示:
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。
这是从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;
}
您可以从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