Java 解析和处理 json 用哪个开源包最好?
Java 中有许多可用的 JSON 库,绝大多数开源包都是将 JSON 完全反序列化为 Java 对象,然后去访问对象中感兴趣的属性值,比如众人皆知的 Jackson、GSON、Genson、FastJson 和 org.json。 还有一类 Json 类库,比如 JsonPATH,Java 中调用特定 DSL 语法,即用 XPath 表达式遍历 JSON 对象,然后在路径的尾端调用最值、平均值、汇总值等函数计算整个 JSON 文档。其实,如果是面向 Json 数据计算的需求,用Open-esProc更方便。但 Open-esProc 和一般 Java 包有所不同,是将数据类型和计算方法封装到一个叫 SPL 的脚本语言中,然后在 Java 程序中调用 SPL 脚本,返回 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*\"))");
…
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语法表达能力强,经常可以简化多层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。比如,连接 MongoDB 计算 Json 数据,参考 用 Java 如何对 MongoDB 执行类似 SQL 的查询?