需求:
使用js脚本,对比两个json字符串对象。
使用API:
ScriptEngine相关,主要使用ScriptEngineManager,ScriptEngine,以及接口Invocable;
背景:
本次使用ScripttEngine主要是完成项目中关于两个字符串对象的对比,本打算使用equal直接对比字符串就可以,但总觉的哪里可能不太好,如果受到空格的影响很容易误判,看api毫无头绪,潇潇洒洒的一页api,感觉什么养分都没有。最终明确思路:
使用ScriptEngine解析出json字符串到Map集合中,然后对比两个Map集合就。
很遗憾,复杂的集合我没办法取,我不知道去获得哪些字段才可以,如果是list集合里嵌套复杂的对象,再嵌套集合啥的。完全无解,存在着太多的未知字段。痛苦的解析了一下午加第二天的上午。最后同事发了两个网址让我看:
Java ScriptEngine 解析js - tigerloveapple - 博客园
http://www.veryhuo.com/a/view/34422.html
当我看到了第一个网址时,豁然开朗,我决定使用js脚本判断。但是这是否和拿出来所有内部东西进行对比进行偏离呢?
最终,我使用了这种方法,直接使用js进行对比,网上查找相关的json对象对比的js函数作为对比方法再最后也对脚本进行预编译,也增加一点java执行js的效率(对js脚本进行编译,供多次使用)代码如下:
预编译:
private staticScriptEngineManager mgr =new ScriptEngineManager();
private staticScriptEngine jsEngine =mgr.getEngineByName("JavaScript");
private static Invocableinvoke =null;
static {
String jsFileName = System.getenv().get("UCAPI_CONFIG_PATH") +"compare.js";//读取js文件
FileReader reader;
try {
reader = newFileReader(jsFileName);
Compilable compEngine =(Compilable)jsEngine;
CompiledScript script = compEngine.compile(reader);
script.eval();//执行指定脚本
if (jsEngineinstanceofInvocable) {
invoke =(Invocable) jsEngine;
}
} catch(FileNotFoundExceptione) {
e.printStackTrace();
} catch(ScriptExceptione) {
e.printStackTrace();
}
}
执行代码:
invoke.invokeFunction("Compare",result,outputParams.getOutValue())
js代码:
functionCompare(objA, objB) {
if (getLength(objA) !=getLength(objB))
return false; // 判断长度是否一致
return CompareObj(objA,objB,true);//默认为true
}
functionCompareObj(objA, objB, flag) {
for (var keyin objA) {
if (!flag) // 跳出整个循环
break;
if(!objB.hasOwnProperty(key)) {
flag = false;
break;
}
if(!isArray(objA[key])) {//子级不是数组时,比较属性值
if(objB[key] != objA[key]) {
flag = false;
break;
}
} else {
if(!isArray(objB[key])) {
flag = false;
break;
}
var oA =objA[key], oB = objB[key];
if(oA.length != oB.length) {
flag = false;
break;
}
for ( var kin oA) {
if (!flag) // 这里跳出循环是为了不让递归继续
break;
flag = CompareObj(oA[k], oB[k],flag);
}
}
}
return flag;
}
functionisObj(object) {
return object
&& typeof (object)=='object'
&&Object.prototype.toString.call(object).toLowerCase() == "[objectobject]";
}
functionisArray(object) {
return object && typeof (object)== 'object' && object.constructor == Array;
}
functiongetLength(object) {
var count = 0;
for ( var iin object)
count++;
return count;
}
最终没有实现去全部解析对象,而是使用js脚本来判断两个json字符串是否相同。