java实现通过xml或者json,生成树状结构数据记录
===========================================
输入数据(xml、json)
输出数据,生成结果
代码实现
TreeNode.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TreeNode implements Serializable, Comparable<TreeNode> {
/**
* 节点类型
*/
private String nodeType;
/**
* 节点名称
*/
private String nodeName;
/**
* 节点id
*/
private Long id;
/**
* 父节点id
*/
private Long pid;
/**
* 节点路径
*/
private String path;
@Override
public String toString() {
return "树结构记录数 {" +
"节点类型='" + nodeType + '\'' +
", 节点名称='" + nodeName + '\'' +
", 节点ID=" + id +
", 父节点ID=" + pid +
", 节点路径='" + path + '\'' +
'}';
}
@Override
public int compareTo(TreeNode o) {
return (this.getPath() + this.getNodeName()).compareTo(o.getPath() + o.getNodeName());
}
// 自定义去重规则
public boolean equals(Object obj){
TreeNode s = (TreeNode) obj;
return this.path.equals(s.path) && this.nodeName.equals(s.nodeName);
}
// 重写hashcode
public int hashCode(){
return (this.path + this.nodeName).hashCode();
}
}
TreeUtil.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fintell.api.demo.common.IdWorker;
import com.fintell.tools.report.XmlUtil;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;
import java.io.IOException;
import java.util.*;
public class TreeUtil {
private static String jsonStr = "{\n" +
"\t\"code\": 200,\n" +
"\t\"msg\": \"OK\",\n" +
"\t\"info\": {\n" +
"\t\t\"alter\": [1, 2, 3],\n" +
"\t\t\"dealin\": [],\n" +
"\t\t\"basic\": {\n" +
"\t\t\t\"entname\": \"测试1\",\n" +
"\t\t\t\"entend\": \"测试2\"\n" +
"\t\t},\n" +
"\t\t\"test1\": {\n" +
"\t\t\t\"test11\": \"123\",\n" +
"\t\t\t\"test12\": \"345\"\n" +
"\t\t},\n" +
"\t\t\"test2\": [{\n" +
"\t\t\t\t\"test21\": \"自然人股东\",\n" +
"\t\t\t\t\"test22\": \"中国\",\n" +
"\t\t\t\t\"test23\": \"30.000000\"\n" +
"\t\t\t},\n" +
"\t\t\t{\n" +
"\t\t\t\t\"test21\": \"自然人股东\",\n" +
"\t\t\t\t\"test22\": \"中国\",\n" +
"\t\t\t\t\"test23\": \"30.000000\"\n" +
"\t\t\t}\n" +
"\t\t]\n" +
"\t}\n" +
"}";
private static final String xmlStr = "<document>\n" +
" <code>200</code>\n" +
" <msg>OK</msg>\n" +
" <info>\n" +
" <alter>1</alter>\n" +
" <alter>2</alter>\n" +
" <alter>3</alter>\n" +
" <basic>\n" +
" <entname>测试1</entname>\n" +
" <entend>测试2</entend>\n" +
" </basic>\n" +
" <test1>\n" +
" <test11>123</test11>\n" +
" <test12>345</test12>\n" +
" </test1>\n" +
" <test2>\n" +
" <test21>自然人股东</test21>\n" +
" <test22>中国</test22>\n" +
" <test23>30.000000</test23>\n" +
" </test2>\n" +
" <test2>\n" +
" <test21>自然人股东</test21>\n" +
" <test22>中国</test22>\n" +
" <test23>30.000000</test23>\n" +
" </test2>\n" +
" </info>\n" +
"</document>";
// 测试
public static void main(String[] args) throws Exception {
// 测试json
Set<TreeNode> treeNodes = jsonOrXmlToTree(jsonStr, 0L, "tri");
for (TreeNode treeNode : treeNodes) {
// 循环打印树状数据,可以存入数据库
System.out.println(treeNode);
}
System.err.println("======================");
// 测试xml
treeNodes = jsonOrXmlToTree(xmlStr, 0L, "tri");
for (TreeNode treeNode : treeNodes) {
// 循环打印树状数据,可以存入数据库
System.out.println(treeNode);
}
}
private static ObjectMapper mapper = new ObjectMapper();
/**
* 将json串转为tree
* @param msg : json或者xml数据
* @param rootId : 根ID
* @param rootPath : 根路径
*/
public static Set<TreeNode> jsonOrXmlToTree(String msg, Long rootId, String rootPath) throws IOException, DocumentException {
// 判断是否为xml数据
if (XmlUtil.isXml(msg)) {
msg = XmlUtil.xmlToJson(msg);
}
System.err.println(msg);
Set<TreeNode> treeNodes = new HashSet<>();
Map<String, String> pathMap = new HashMap<>();
// 将json转为map结构
Map maps = mapper.readValue(msg, Map.class);
// 循环map,将数机构存入set集合
/**
* tri : 默认父节点
* path : 默认根节点的父节点为tri,可以空着
*/
transToTree(maps,rootId, rootPath, treeNodes, pathMap);
return treeNodes;
}
/**
* map转树结构
* @param map : map
* @param pid : 父节点ID
* @param path : 父节点路径
*/
private static Object transToTree(Object map, Long pid, String path, Set<TreeNode> treeNodes, Map<String, String> pathMap) {
if (map == null) {
return false;
}
try {
Map mp = null;
List ls = null;
if (map instanceof Map || map instanceof LinkedHashMap) {
mp = (LinkedHashMap) map;
for (Iterator ite = mp.entrySet().iterator(); ite.hasNext(); ) {
Map.Entry e = (Map.Entry) ite.next();
// 生成唯一标识,可以依据自身情况,使用其它方式
Long idNew = IdWorker.nextIdLong();
String pathNew = path + (StringUtils.isEmpty(path) ? "" : ".") + e.getKey();
if (pathMap.containsKey(path)) {
pathNew = pathMap.get(path) + "." + e.getKey();
}
if (e.getValue() instanceof String) {
treeNodes.add(new TreeNode("字符", e.getKey().toString(), idNew, pid, pathNew));
} else if (e.getValue() instanceof LinkedHashMap) {
treeNodes.add(new TreeNode("节点", e.getKey().toString(), idNew, pid, pathNew));
transToTree((LinkedHashMap) e.getValue(), idNew, pathNew, treeNodes, pathMap);
} else if (e.getValue() instanceof ArrayList) {
treeNodes.add(new TreeNode("数组", e.getKey().toString(), idNew, pid, pathNew));
transToTree((ArrayList) e.getValue(), idNew, pathNew, treeNodes, pathMap);
} else {
treeNodes.add(new TreeNode("字符", e.getKey().toString(), idNew, pid, pathNew));
}
}
}else if (map instanceof List || map instanceof ArrayList) {
ls = (ArrayList) map;
for (int i = 0; i < ls.size(); i++) {
if (ls.get(i) instanceof LinkedHashMap) {
transToTree((LinkedHashMap) ls.get(i), pid, path, treeNodes, pathMap);
} else if (ls.get(i) instanceof ArrayList) {
transToTree((ArrayList) ls.get(i), pid, path, treeNodes, pathMap);
}
}
}
} catch (Exception e) {
throw e;
}
return null;
}
}
XmlUtil.java
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.dom4j.*;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.util.List;
public class XmlUtil {
/**
* 判断字符串是否为xml
*/
public static boolean isXml(String str) {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
builder.parse( new InputSource( new StringReader( str )));
return true;
} catch (Exception e) {
return false;
}
}
/**
* xml转json
*/
public static String xmlToJson(String xmlStr) throws DocumentException {
Document doc= DocumentHelper.parseText(xmlStr);
JSONObject json = new JSONObject();
XmlUtil.dom4j2Json(doc.getRootElement(),json);
return json.toJSONString();
}
private static void dom4j2Json(Element element, JSONObject json) {
// 如果是属性
for (Object o : element.attributes()) {
Attribute attr = (Attribute) o;
if (!CommonUtils.isEmpty(attr.getValue())) {
json.put("@" + attr.getName(), attr.getValue());
}
}
List<Element> chdEl = element.elements();
if (chdEl.isEmpty() && !CommonUtils.isEmpty(element.getText())) {//如果没有子元素,只有一个值
json.put(element.getName(), element.getText());
}
for (Element e : chdEl) {//有子元素
if (!e.elements().isEmpty()) {//子元素也有子元素
JSONObject chdjson = new JSONObject();
dom4j2Json(e, chdjson);
Object o = json.get(e.getName());
if (o != null) {
JSONArray jsona = null;
if (o instanceof JSONObject) {//如果此元素已存在,则转为jsonArray
JSONObject jsono = (JSONObject) o;
json.remove(e.getName());
jsona = new JSONArray();
jsona.add(jsono);
jsona.add(chdjson);
}
if (o instanceof JSONArray) {
jsona = (JSONArray) o;
jsona.add(chdjson);
}
json.put(e.getName(), jsona);
} else {
if (!chdjson.isEmpty()) {
json.put(e.getName(), chdjson);
}
}
} else {//子元素没有子元素
for (Object o : element.attributes()) {
Attribute attr = (Attribute) o;
if (!CommonUtils.isEmpty(attr.getValue())) {
json.put("@" + attr.getName(), attr.getValue());
}
}
if (!e.getText().isEmpty()) {
json.put(e.getName(), e.getText());
}
}
}
}
}