1.導入json相關的jar包
2.JsonTreeHelper.java
3.調用getTreeJsonStr方法:
nodesNameBySeq:待分組的節點名稱.將樹節點對應的實體類的成員名稱放到此數組裏面,順序是{"根節點","子節點1","子節點2"...}
data:數據列表,List<實體類> data ;
編寫原理:
1).首先用groupByNodeName將數據分組
用Java中的Field進行字段比較,來獲得相對應的成員字段,以及成員變量的名稱,這裏要用getDeclaredFields方法來獲得,否則,private聲明的成員是無法得到Field的
將得到的fieldIndex全部放到數組中保存,便於以後的使用,field[fieldIndex]可以得到相應的字段
2).構造一個tree的json形式的類:裏面有幾個重要的成員:{id,text,state}這種形式用JsonObject.fromObject(jsonObj}能直接轉換爲tree所需要的json,並且,這個類中要有一
個children字段,保存子節點的數據
3).recursiveTree方法
# 此方法內要遞歸遍歷樹,返回一個list,list中是一個JsonTreeObj自定義的一個類,其中的children還可以保存一個JsonTreeObj,這樣就可以實現嵌套
#在遞歸之前,首先要有一個成員變量(全局變量)來記錄要分組的節點索引
先進行一次分組,得到的map就是JsonTreeObj,通過構造方法可以實現轉換,這樣,轉換過來的JsonTreeObj纔是我們的Tree-json,但這只是一次調用
是否再次分組,要用事先準備好的 fieldIndex長度或者nodesNameBySeq進行判斷,如果要繼續分組,那麼需要移除map中每條數據中的list並重新分組成map.
即:用新分組的List替換以前未分組的List
返回之後,返回分組好的JsonTreeObj數據,此時的list差不多和需要的json相仿但是,還要做下字符串的調整
4).replaceText
用此方法來替換最深層節點的文本,否則字段中無text,會出現undefine
4.示例
1)要構造的樹
2)要構造的json
[
{
"children": [
{
"children": [
{
"children": [
{
"address": "bj",
"text": "id1",
"name": "wang'ao1",
"occupation": "student"
}
],
"id": "0.5715806450144063",
"state": "closed",
"text": "student"
}
],
"id": "0.4010186645348438",
"state": "closed",
"text": "bj"
},
{
"children": [
{
"children": [
{
"address": "bj11",
"text": "id12",
"name": "wang'ao1",
"occupation": "student"
}
],
"id": "0.188373241944635",
"state": "closed",
"text": "student"
},
{
"children": [
{
"address": "bj11",
"text": "id11",
"name": "wang'ao1",
"occupation": "teacher"
}
],
"id": "0.9566645560486874",
"state": "closed",
"text": "teacher"
}
],
"id": "0.6062106288555755",
"state": "closed",
"text": "bj11"
}
],
"id": "0.6856242232995936",
"state": "closed",
"text": "wang'ao1"
},
{
"children": [
{
"children": [
{
"children": [
{
"address": "bj",
"text": "id1",
"name": "wang'ao",
"occupation": "student"
}
],
"id": "0.5044856120294572",
"state": "closed",
"text": "student"
}
],
"id": "0.2021652373692504",
"state": "closed",
"text": "bj"
},
{
"children": [
{
"children": [
{
"address": "bj11",
"text": "id12",
"name": "wang'ao",
"occupation": "student"
}
],
"id": "0.7096934456298796",
"state": "closed",
"text": "student"
},
{
"children": [
{
"address": "bj11",
"text": "id11",
"name": "wang'ao",
"occupation": "teacher"
}
],
"id": "0.8679325026402117",
"state": "closed",
"text": "teacher"
}
],
"id": "0.6940289758188156",
"state": "closed",
"text": "bj11"
}
],
"id": "0.08304442224761122",
"state": "closed",
"text": "wang'ao"
}
]
3)實體類
/**
* @author wang'ao
*
*/
public class TestEntity {
private String name ;
private String ids ;
private String address ;
private String occupation ;
public String getOccupation() {
return occupation;
}
public void setOccupation(String occupation) {
this.occupation = occupation;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIds() {
return ids;
}
public void setId(String ids) {
this.ids = ids;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public TestEntity(String name, String ids, String address, String occupation) {
super();
this.name = name;
this.ids = ids;
this.address = address;
this.occupation = occupation;
}
@Override
public String toString() {
return "TestEntity [name=" + name + ", id=" + ids + ", address="
+ address + "]";
}
}
4)測試
/**
* @author wang'ao
*
*/
public class Test {
public static void main(String[] args) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
TestEntity te1 = new TestEntity("wang'ao","id1","bj","student") ;
TestEntity te2 = new TestEntity("wang'ao","id11","bj11","teacher") ;
TestEntity te3 = new TestEntity("wang'ao","id12","bj11","student") ;
TestEntity te4 = new TestEntity("wang'ao1","id1","bj","student") ;
TestEntity te5 = new TestEntity("wang'ao1","id11","bj11","teacher") ;
TestEntity te6 = new TestEntity("wang'ao1","id12","bj11","student") ;
List<Object> list = new ArrayList<Object>() ;
list.add(te1) ;
list.add(te2) ;
list.add(te3) ;
list.add(te4) ;
list.add(te5) ;
list.add(te6) ;
System.out.println("jsonTree:" +
JsonTreeHelper.getTreeJsonStr(new String[]{"name","address","occupation","ids"}, list)
);
}
}
JsonTreeHelper.java
/**
*
* @version V1.0
*/
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
/**
* 用途:json樹的數據生成類
* 描述:將數據列表轉換成相應的tree所必需的JSON格式
* 說明:N級節點樹,默認樹節點是關閉的
*
* @author wang'ao
*
*/
public class JsonTreeHelper {
/**
* 用於頁面傳遞JSON數據的類,id:xx text:xx children:xx
* 將從數據庫查詢到的數據,用這個類進行打包,而可以將這個類直接轉換成 指定的格式的JSON字符串
*
* tip:如有需要,直接繼承,並添加一個自定義字段
*
* @author wang'ao
*
*/
public static class JsonTreeObj {
/** 必需的id **/
private String id;
/** 顯示的節點文本 **/
private String text;
/** 是否是關閉狀態 **/
private String state;
/** 子 **/
private List<Object> children;
/**
*
* @param text
* 節點的文本名字
* @param children
* 內部節點集合
*/
public JsonTreeObj(String rootNode, List<Object> children) {
/** 保證id不重複 **/
this.id = Math.random() + "";
this.state = "closed";
this.text = rootNode;
this.children = children;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public List<Object> getChildren() {
return children;
}
public void setChildren(List<Object> children) {
this.children = children;
}
}
/**
* 用途:轉換tree形式數據 用例: 實體類:class People{private String name ;private String
* hometown ;private String occupation ; set...;get...}
* 調用方法:getTreeJsonStr(new String[]{"hometown","occupation"},data);
* 說明:表示以hometown爲根節點,occupation字段爲子節點所構成的樹
*
* @param nodesNameBySeq
* 樹節點名字數組 {"根節點","子節點1","子節點2",...} ,此處的名字應是對應的實體類的成員名.
* 如:有一個成員{private String type ;} 根節點是"type"
* @param data
* 數據
* @return tree形式的JSON數據
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static String getTreeJsonStr(String[] nodesNameBySeq,List<Object> data) throws IllegalArgumentException,
IllegalAccessException {
int[] fieldIndex = new int[nodesNameBySeq.length];
// 優化標記
int end = 0;
Field[] fields = data.get(0).getClass().getDeclaredFields();
for (int i = 0; i < nodesNameBySeq.length; i++) {
for (int j = 0; j < fields.length; j++) {
if (nodesNameBySeq[i].equals(fields[j].getName())) {
fieldIndex[i] = j;
end++;
if (end == nodesNameBySeq.length)
break;
}
}
}
// 替換成text字段
return replaceText(JSONArray
.fromObject(recursiveTree(data, fieldIndex)).toString(),
nodesNameBySeq[nodesNameBySeq.length - 1], "text");
}
/**
* 將數據根據根節點進行分組
*
* @param fieldIndex
* 根節點成員字段所對應折field索引
* @param list
* 數據列表
* @return 分組好的map數據
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
private static Map<String, List<Object>> groupByNodeName(
Integer fieldIndex, List<Object> list)
throws IllegalArgumentException, IllegalAccessException {
// 準備集合
Map<String, List<Object>> readyMap = new HashMap<String, List<Object>>();
for (int i = 0; i < list.size(); i++) {
java.lang.reflect.Field[] field = (java.lang.reflect.Field[]) list
.get(i).getClass().getDeclaredFields();
field[fieldIndex].setAccessible(true);
List<Object> find = readyMap.get(field[fieldIndex].get(list.get(i))
.toString());
if (readyMap.isEmpty() || find == null) {
List<Object> similar = new ArrayList<Object>();
similar.add(list.get(i));
readyMap.put(field[fieldIndex].get(list.get(i)).toString(),
similar);
} else {
find.add(list.get(i));
readyMap.put(field[fieldIndex].get(list.get(i)).toString(),
find);
}
}
return readyMap;
}
private static int fIndex = 0;
/**
* 遍歷所有節點(遞歸調用)
*
* @param data
* @param fieldIndexF
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
private static List<JsonTreeObj> recursiveTree(List<Object> data,
int[] fieldIndexF) throws IllegalArgumentException,
IllegalAccessException {
// 先進行一次分組
Map<String, List<Object>> firstGroupedData = groupByNodeName(
fieldIndexF[fIndex], data);
List<JsonTreeObj> jsonTrees = new ArrayList<JsonTreeObj>();
// 第一次分組的數據
Iterator<Map.Entry<String, List<Object>>> it = firstGroupedData
.entrySet().iterator();
int i = 0;
List<Object> list;
// 遍歷map
while (it.hasNext()) {
Map.Entry<String, List<Object>> entry = it.next();
jsonTrees.add(new JsonTreeObj(entry.getKey(), entry.getValue()));
if (fieldIndexF.length > 1 && fIndex < fieldIndexF.length - 2) {
fIndex++;
// **.clear()方法要清除指針,所以要用new方法實例化
list = new ArrayList<Object>(entry.getValue());
jsonTrees.get(i).getChildren().clear();
jsonTrees.get(i).getChildren()
.addAll((recursiveTree(list, fieldIndexF)));
}
i++;
}
fIndex--;
return jsonTrees;
}
/**
* 將JSON串中的字符替換,如:"post" -> "text" ,這樣可以正常顯示文本,否則 undefine
*
* @param src
* 源JSON
* @param replace
* 要替換的字段
* @param changedTxt
* 替換之後的字段
* @return 替換完成之後的字段
*/
private static String replaceText(String src, String replace,
String changedTxt) {
return src.replaceAll("\"" + replace + "\"", "\"" + changedTxt + "\"");
}
}