将 Json 转换为 Java 对象,动态且灵活的方法是什么?
解决办法:esProc - Java 专业计算包
esProc 是专门用于基于 Java 计算的类库,旨在简化 Java 代码。 SPL 是基于 esProc 计算包的脚本语言,和 Java 程序一起部署,可以理解为库外存储过程,用法和 Java 程序中调用存储过程相同,通过 JDBC 接口传递给 Java 程序执行,实现结构化计算。它非常轻巧,语法简单,类似执行 SQL 的方式计算 Json 数据,返回 ResultSet 对象。
文件 EO.json 存储一批员工信息,以及属于员工的多个订单,部分数据如下:
[{
"_id": {"$oid": "6074f6c7e85e8d46400dc4a7"},
"EId": 7,"State": "Illinois","Dept": "Sales","Name": "Alexis","Gender": "F","Salary": 9000,"Birthday": "1972-08-16",
"Orders": [
{"OrderID": 70,"Client": "DSG","SellerId": 7,"Amount": 288,"OrderDate": "2009-09-30"},
{"OrderID": 131,"Client": "FOL","SellerId": 7,"Amount": 103.2,"OrderDate": "2009-12-10"}
]
}
{
"_id": {"$oid": "6074f6c7e85e8d46400dc4a8"},
"EId": 8,"State": "California", ...
}]
用 SPL 条件查询实现如下:
A |
|
1 |
=json(file("D:\\data\\EO.json").read()) |
2 |
=A1.conj(Orders) |
3 |
=A2.select(Amount>500 && Amount<=2000 && like@c(Client,"*bro*")) |
上面代码先将Json读为多层的序表对象,再用conj函数合并所有订单,之后用select函数完成条件查询。
这段代码可在esProc IDE中调试执行,存为脚本文件(比如condition.dfx),通过JDBC接口在JAVA中调用,具体代码如下:
package Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class test1 {
public static void main(String[] args)throws Exception {
Class.forName("com.esproc.jdbc.InternalDriver");
Connection connection =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("call condition()");
printResult(result);
if(connection != null) connection.close();
}
…
}
上面的用法类似存储过程,其实 SPL 也支持类似 SQL 的用法,即无须脚本文件,直接将 SPL 嵌入 JAVA 程序,代码如下:
…
ResultSet result = statement.executeQuery("=json(file(\"D:\\data\\EO.json\").read()).conj(Orders).select(Amount>500 && Amount<=3000 && like@c(Client,\"*bro*\"))");
…
与 Java 程序集成,详情参考Java 如何调用 SPL 脚本
SPL 可以实现分组汇总和关联计算,代码如下:
A |
B |
|
1 |
=json(file("D:\\data\\EO.json").read()) |
|
2 |
=A1.conj(Orders) |
|
3 |
=A2.select(Amount>1000 && Amount<=3000 && like@c(Client,"*s*")) |
/条件查询 |
4 |
=A2.groups(year(OrderDate);sum(Amount)) |
/分组汇总 |
5 |
=A1.new(Name,Gender,Dept,Orders.OrderID,Orders.Client,Orders.Client,Orders.SellerId,Orders.Amount,Orders.OrderDate) |
/关联计算 |
从上面代码可以看出,SPL语法表达能力很强,不仅可以完成常用的计算,代码简短易懂,且容易集成。SPL对点操作符的支持更直观,在实现关联计算时可直接从多层数据取值,代码更加简练。
SPL语法表达能力强,经常可以简化多层json的计算,比如:文件JSONstr.json的runners字段是子文档,子文档有3个字段:horseId、ownerColours、trainer,其中trainer含有下级字段trainerId ,ownerColours是逗号分割的数组。部分数据如下:
[
{
"race": {
"raceId":"1.33.1141109.2",
"meetingId":"1.33.1141109"
},
...
"numberOfRunners": 2,
"runners": [
{ "horseId":"1.00387464",
"trainer": {
"trainerId":"1.00034060"
},
"ownerColours":"Maroon,pink,dark blue."
},
{ "horseId":"1.00373620",
"trainer": {
"trainerId":"1.00010997"
},
"ownerColours":"Black,Maroon,green,pink."
}
]
},
...
]
现在要按 trainerId分组,统计每组中 ownerColours的成员个数。可用下面的SPL实现本计算。
A |
|
1 |
=json(file("/workspace/JSONstr.json").read()) |
2 |
=A1(1).runners |
3 |
=A2.groups(trainer.trainerId; ownerColours.array().count():times) |
在数据源方面,SPL表现优秀,不仅有专用函数读取文件中的json,也支持读取MongoDB、Elasticsearch、WebService等多种数据源中的Json。
最后说下esProc的配置。在 esProc IDE 读写计算Json是esProc的基本功能,无需额外配置(MongoDB等数据源除外)
连接 MongoDB 计算 Json 数据,参考 用 Java 如何对 MongoDB 执行类似 SQL 的查询?
更多 Json 计算示例,参考 JSON 数据计算与入库.pdf
英文版