java - 在 DataWeave 中递归遍历和展平 JSON 对象
问题描述
我想遍历并展平具有以下结构的大型 JSON 文件,显示产品层次结构(将其视为在线商店中的导航):
productGroups: [
{
"key": "child 1"
...
"childrenProductGroups": [
{
"key": "child 1.1",
...,
"childrenProductGroups": []
},
{
"key": "child 1.2"
...
"childrenProductGroups": [
{
"key": "child 1.2.1",
...,
"childrenProductGroups": [
{
"key": "child 1.2.1.1",
...,
childrenProductGroups": [
...
]
}
]
},
{
"key": "child 1.2.2",
...,
"childrenProductGroups": []
}
]
},
{
"key": "child 1.3",
...,
"childrenProductGroups": [
...
]
}
]
},
{
"key": "child 2",
...,
"childrenProductGroups": [
...
]
},
{
"key": "child 3",
...,
"childrenProductGroups": [
...
]
}
]
我想以这样的格式将它们展平:
{
"hierarchieSet": [
{
"Nodeid": "00000001", # Number in this json
"Nodename": "child 1",
"Tlevel": "01", # First child of product group
"Parentid": "00000000", # Parent is null
"Childid": "00000002", # Child node number
"Nextid": "00000008" # Node number on the same level (child 2)
},
{
"Nodeid": "00000002",
"Nodename": "child 1.1",
"Tlevel": "02",
"Parentid": "00000001",
"Childid": "00000003",
"Nextid": "00000003"
},
{
"Nodeid": "00000003",
"Nodename": "child 1.2",
"Tlevel": "02",
"Parentid": "00000002",
"Childid": "00000005",
"Nextid": "00000007"
},
{
"Nodeid": "00000004",
"Nodename": "child 1.2.1",
"Tlevel": "03",
"Parentid": "00000003",
"Childid": "0000005",
"Nextid": "00000006"
}
,
{
"Nodeid": "00000005",
"Nodename": "child 1.2.1.1",
"Tlevel": "04",
"Parentid": "00000004",
"Childid": "0000000", #No more children
"Nextid": "00000000"
},
{
"Nodeid": "00000006",
"Nodename": "child 1.2.2",
"Tlevel": "03",
"Parentid": "00000003",
"Childid": "0000000",
"Nextid": "00000000"
},
{
"Nodeid": "00000007",
"Nodename": "child 1.3",
"Tlevel": "02",
"Parentid": "00000001",
"Childid": "0000000",
"Nextid": "00000000"
},
{
"Nodeid": "00000008",
"Nodename": "child 2",
"Tlevel": "01",
"Parentid": "00000000",
"Childid": "0000009", # 00000009 not shown
"Nextid": "00000014" #
},
...
{
"Nodeid": "000000014",
"Nodename": "child 3",
"Tlevel": "01",
"Parentid": "00000000",
"Childid": "00000015",
"Nextid": "00000000" # 00000010 does not exist
}
]
}
因此,我确定了一些主要问题:
- 树结构的递归
- 转换元素
- 扁平化结构
- 跟踪父母、兄弟姐妹和孩子
- 跟踪递归级别
- 格式化数字
我试图通过两种不同的方法来解决这个问题:
- 使用 DataWeave 转换所有元素
- 使用Java遍历结构
由于我对函数式编程还很陌生,因此我将更多的精力放在了 Java 实现上,但遇到了许多问题。
Java 方法
读取 json > Init Tree var 并为顶级数组调用中的每个元素分配 Java 实例 > 。
树.java:
traverse(data, level)
Tree.java
import org.json.JSONObject;
public class Tree {
private int id = 0;
private List<Node> nodes = new ArrayList<Node>();
public Tree() {
nodes.add(new Node("01", "00000001", "HOME", "01", "00000000", "00000002", "00000000"));
}
public void traverse(String data, int level) {
System.out.println(data);
// TODO parse json
}
private void visit(JSONObject parent, JSONObject node, int level) {
id++;
nodes.add(new Node("01", String.valueOf(id), node.getString("key"), String.valueOf(level), "", "", ""));
}
public List<Node> getNodes() {
return nodes;
}
private static class Node {
private String zshop, nodename, parentid, childid, nextid, nodeid, tlevel;
public Node(String zshop, String nodeid, String nodename, String tlevel, String parentid, String childid, String nextid) {
this.zshop = zshop;
this.nodeid = nodeid;
this.nodename = nodename;
this.tlevel = tlevel;
this.parentid = parentid;
this.childid = childid;
this.nextid = nextid;
}
}
}
调用调用操作时,我使用此有效负载:
%dw 2.0
output application/java
---
{
data: vars.rootMessage.payload as String,
level: 1
}
但这会产生以下错误:
“无法强制对象 { 编码:UTF-8,mediaType:text/json;charset=UTF-8,mimeType:text/json,原始:org.mule.weave.v2.el.SeekableCursorStream@50ecee52 } (org.mule. weave.v2.el.MuleTypedValue@511ba9cc) 到字符串
5| 数据:vars.rootMessage.payload 作为字符串,^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 跟踪:在 main (line : 5, column: 7)" 评估表达式:"%dw 2.0 output application/java --- { data: vars.rootMessage.payload as String, level: 1 }"。
我尝试了很多事情:
- 将其转换为
ProductGroup
我用 Java 编写的对象 - 尝试将检索到的对象转换为
org.json.JSONObject
- 尝试缓冲和读取
vars.rootMessage.payload (Binary)
但是我无法解决任何这些问题。
DataWeave 方法 我的 .dw 脚本
%dw 2.0
fun append
(item: Object, acc: Object = {
}) = acc ++ item
fun mapper(item: Object) =
{
Zshop: "01",
Nodeid: "00000000",
Nodename: item.key as Number as String {format: ""},
Tlevel: "02",
Parentid: "00000000",
Childid: "00000000",
Nextid: "00000000"
}
fun traverse(a: Array, level: Number) =
a map $ flatMap(value, index) -> value
output application/json
---
{
test: payload.productGroups reduce (item, acc) -> append(mapper(item), acc)
}
我试图解决一些问题的地方。mapper(item)
应该创建我可以附加到最终输出的 json 对象appender(item, acc)
。递归已经勾勒出来,但还不是我主要关心的问题。
这产生了这个结果:
(original payload),
"Zshop": "01",
"Nodeid": "00000000",
"Nodename": "800",
"Tlevel": "02",
"Parentid": "00000000",
"Childid": "00000000",
"Nextid": "00000000",
"Zshop": "01",
"Nodeid": "00000000",
"Nodename": "110",
"Tlevel": "02",
"Parentid": "00000000",
"Childid": "00000000",
"Nextid": "00000000",
"Zshop": "01",
"Nodeid": "00000000",
"Nodename": "720",
"Tlevel": "02",
"Parentid": "00000000",
"Childid": "00000000",
"Nextid": "00000000",
"Zshop": "01",
"Nodeid": "00000000",
"Nodename": "710",
"Tlevel": "02",
"Parentid": "00000000",
"Childid": "00000000",
"Nextid": "00000000",
...
我想知道为什么我在没有任何对象结构的情况下得到一个平坦的结果。
我的问题:
- Java:为什么我不能转换字符串或者它是如何正确完成的
- DataWeave:有没有我看不到的简单解决方案?
- 为什么它是一个平坦的结果而不是一个对象?
reduce
和功能的用法是否flatMap
正确?
欢迎任何帮助和/或反馈。
解决方案
Java:为什么我不能转换字符串或者它是如何正确完成的
JSON 不是字符串。使用 write(payload,'application/json') 获得字符串。
DataWeave:有没有我看不到的简单解决方案?
只需传递对象,它是 Java 中的 Map。由于它是树 - 每个分支都是此 Map 中的另一个 Map。
为什么它是一个平坦的结果而不是一个对象?
它总是对象。Java世界中没有其他东西。
为此目的,reduce 和 flatMap 函数的用法是否正确?
不,mapObject 和递归应该是好方法。
推荐阅读
- ios - 如何不经常更新 Firebase 中的位置数据?
- matlab - 如何在 matlab 中使用带有 gscatter3 的颜色图?
- javascript - React hook useSelector 值在异步函数中未更改
- javascript - Var中的Mapbox多个If语句
- php - 高级自定义字段日期选择器数据在自定义 wordpress 后循环中使用时会出错
- python - 使用 Abseil 与直接调用 main()?
- .net-core - 如何将 DI 代码集中在 lambda function.cs 之外,而是集中到专用类中以更好地分离关注点
- java - RSA 加密 Java/Kotlin
- tabulator - 如何将子菜单添加到制表符上下文菜单?
- java - 使 export JAVA_HOME=`/usr/libexec/java_home -v 1.8` 永久化