SPL 实践:解析并过滤来自 RESTful 的多层 JSON
实践背景
通过 RESTful 交换数据很方便,但接收数据后如何继续计算会有点麻烦。SPL 提供了 HTTP 接口,可以直接读取 RESTful 的数据后进行计算。
如下例,电商业务中订单数据的访问被封装成 REST 接口供其他业务访问。
访问地址:
http://111.198.29.168:8503/getOrdershttp://111.198.29.168:8503/getOrders/bDate/eDate
其中:bDate 与 eDate 为路径参数,直接在 URL 中拼接即可,参数代表查询的起始和结束日期。
接口返回的 JSON 格式数据如下:
[
{
"order_id": "AMZ123001",
"order_date": "2023-11-11 18:00:17",
"order_status": "processing",
"user_info": {
"user_id": "USR001",
"username": "john_doe",
"email": "john_doe@example.com",
"country": "USA",
"city": "New York"
},
"payment_info": {
"payment_method": "credit_card",
"total_amount": 0
},
"order_details": [
{
"product_id": "PD001",
"product_name": "Smartphone",
"price": 599.99,
"quantity": 1
},
{
"product_id": "PD002",
"product_name": "Laptop",
"price": 1299.99,
"quantity": 1
}
]
},
…
]
现在分析 2023 年的订单,从所有未取消的订单中找出本年购买金额最多的前 5 名客户,以便为其发放礼品奖励。
实践过程
编辑脚本
打开 SPL IDE 编写脚本:
A |
|
1 |
=httpfile("http://111.198.29.168:8503/login4get?nameOrEmail=tom&userPassword="+md5("mypass")+"rememberLogin=true“:"UTF-8" ).read() |
2 |
=A1.property("Set-Cookie") |
3 |
=httpfile("http://111.198.29.168:8503/getOrders"+"/"+bDate+"/"+eDate:"UTF-8";"Cookie":A2).read() |
4 |
=json(A3) |
5 |
=A4.select(order_status!="canceled") |
6 |
=A5.groups(user_info.user_id;sum(order_details.price*order_details.quantity):amt) |
7 |
=A6.top(-5;amt) |
8 |
return json(A7) |
A1-A2:RESTful 访问鉴权
A3:访问数据接口,根据起止日期获取本年订单数据,其中 bDate、eDate 为脚本参数
A4:结构化 JSON 串,转换为多层序表
User_info 的下一层:
A5:过滤数据,返回所有未取消订单
A6:按照用户分组汇总订单金额。这里通过 user_info.user_id 的方式访问多层序表中各个层次的数据(有了多层序表就能天然适应 JSON 的多层结构)
A7:获得金额最大的前 5 名用户(包括用户名和金额)
A8:结果以 JSON 格式返回
Java 调用
参考 Java 如何调用 SPL 脚本 ,将 esproc-bin-xxxx.jar 和 icu4j-60.3.jar,以及配置文件 raqsoftConfig.xml 引入到项目后,通过 JDBC 调用 SPL 脚本或执行 SPL 语句。
像调用存储过程一样执行 SPL 脚本文件:
Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn= DriverManager.getConnection("jdbc:esproc:local://");
PreparedStatement st = conn.prepareCall("call restJsonParse (?,?)");
st.setObject(1, "2023-01-01");
st.setObject(2, "2023-12-31");
st.execute();
ResultSet rs = st.getResultSet();
或者直接执行 SPL 语句,将 IDE 中的脚本选中并复制粘贴到 Java 字符串中,就可以得到这样的串:
String spl = "==httpfile(\"http://111.198.29.168:8503/login4get?nameOrEmail=tom&userPassword=\"+md5(\"mypass\")+\"rememberLogin=true“:\"UTF-8\" ).read()\n" +
"=A1.property(\"Set-Cookie\")\n" +
"=httpfile(\"http://111.198.29.168:8503/getOrders\"+\"/\"+bDate+\"/\"+eDate:\"UTF-8\";\"Cookie\":A2).read() \n" +
"=json(A3)\n" +
"=A4.select(order_status!=\"canceled\")\n" +
"=A5.groups(user_info.user_id;sum(order_details.price*order_details.quantity):amt)\n" +
"=A6.top(-5;amt)\n" +
"return json(A7)";
需要注意的是,脚本串要以双等(==)号开头。
下面执行脚本:
Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn= DriverManager.getConnection("jdbc:esproc:local://");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(spl);
输出结果集得到如下 JSON 串:
[{"user_id":"USR001","amt":2399.96},{"user_id":"USR008","amt":1079.8799999999999},{"user_id":"USR005","amt":999.96},{"user_id":"USR010","amt":879.92},{"user_id":"USR007","amt":799.96}]
这样就完成了 RESTful 解析和计算,计算结果可以直接返回或传递给其他程序继续使用。
英文版