ExtJs – Server에서 Tree구조 데이터를 JSON 데이터로 전송

ExtJs의 Tree Panel구조를 이용하여 메뉴나 선택항목을 구성하는 경우 데이터를 Ajax 등을 통해 Data Model로 내려받아 Panel에 뿌려야 한다(그렇지 않으면 Tree를 갱신하기도 어려워지고 공통모듈을 사용하기 어려워 진다).
이 때 서버쪽에서 Tree구조의 json 데이터를 내려주기 위해서는 결국 서버쪽에서 json데이터를 만들기 전 먼저 tree 구조로 데이터를 재정렬해서 json데이터 형태로 전환해야 한다.

많은 검색 끝에 찾은 팁은 다음과 같다.

데이터 조회(php)

...
db조회
...
    $data = array();
    $i = 0;
    while ( $row = dbnext($result) ) { // 쿼리 결과를 loop 돌면서 배열에 채우는 부분
          $data[$i] = array();
          $data[$i]['id'] = $row[0];    // 정렬을 위한 키값을 읽음. 이를 id라고 하는 field에 저장
          $data[$i]['parent_id] = $row[4];  // 정렬을 위해 부모(parent) 키값을 읽음
          $data[$i]['leaf'] = true;         // 모든 노드를 잠정적으로 leaf로 저장
          for ( $idx = 1; $idx <= 3; $idx++ ) { // 조회한 field값을 배열에 입력 받음 
              $field_name = "field" . $idx;
              $data[$i][$field_name] = $row[$idx];
          }
          $i++;
    }
...
db close

정렬하는 부분(php)

         $itemsByReference = array();
         foreach($data as $key => &$item) {
               $itemsByReference[$item['id']] = &apm;$item;
         }

         foreach($data as $key => &$item)
               if($item['parent_id'] && isset($itemsByRefence[$item['parent_id']])) {
                    $itemsByReference[$item['parent_id']['children'][] = &$item;
                    $itemsByReference[$item[parent_id']['expanded'] = true;
                    unset($itemsByReference[$item['parent_id']]['leaf']);
               }

         foreach($data as $key => &$item) {
               if($item['parent_id'] && isset($itemsByReference[$item['parent_id']]))
                    unset($data[$key]);
         }

         if ($i > 0) {
             print json_encode($data);
         }

php에서 지원하는 json과 배열의 call by reference가 jsp에서는 지원되지 않는다.
그래서 json은 별도 class를 사용해서 해결했고(org.json.*), 데이터의 정렬은 stack 구조를 이용하여 구현했다.

데이터 조회(jsp)

    JSONArray   jData = new JSONArray();
    HashMap subData;
...
    데이터 조회
...
       i = 0;
       while ( row.next() ) {
            subData = new HashMap();
            subData.put("id", row.getString(2));         // 키값을 입력한다.
            if ( i == 0 ) thisTermAmount = Double.valueOf(row.getString(13));
            for ( idx = 1;  idx <= 3; n++ ){
                  subData.put("field" + String.valueOf(idx), row.getString(idx));
             }
             subData.put("seq", row.getString(4));    // seq와 depth 필드가 필수다
             subData.put("depth", row.getString(5));
             subData.put("parent_id", row.getString(6));
             subData.put("leaf", true);
             jData.put(i, subData);
             i++;
        }
     if ( i > 0 ) 
             out.println(Utils.TreeJson(jData).toString());

배열을 그대로 이용하여서는 json으로 변환하기 힘들어 JSONArray와 HashMap()을 이용하여 데이터를 저장하여 이를 다시 재정렬하는 구조로 작성하였다.

정렬하는 부분(jsp)

import java.util.*;
import org.json.*;

public class Utils {

    Utils() {}

    public static JSONArray TreeJson(JSONArray jData)
    {
        int     len, m;
        Stack   s1 = new Stack();
        Stack   s2 = new Stack();
        JSONObject  j1, j2;

        try {
            j1 = jData.getJSONObject(0);
            s1.push(j1);
            for ( m = 1; m < jData.length(); m++) {
                j2 = jData.getJSONObject(m);
                if ( Integer.parseInt(j1.get("depth").toString()) <= Integer.parseInt(j2.get("depth").toString()) ) {
                     s1.push(j2);
                     j1 = j2;
                 }
                 else if ( Integer.parseInt(j1.get("depth").toString()) > Integer.parseInt(j2.get("depth").toString())  ) {
                    while (  Integer.parseInt((s1.peek()).get("depth").toString()) > Integer.parseInt(j2.get("depth").toString()) ) {
                        JSONArray children = new JSONArray();
                        int     lvl = Integer.parseInt((s1.peek()).get("depth").toString());
                        while ( Integer.parseInt((s1.peek()).get("depth").toString()) == lvl ) {
                            s2.push(s1.pop());
                        }
                        while(s2.size() > 0 ) {
                            children.put(s2.pop());
                        }
                        j1 = s1.pop();
                        j1.put("children", children);
                        j1.remove("leaf");
                        j1.put("leaf", false);
                        s1.push(j1);
                    }
                    s1.push(j2);
                    j1 = j2;
                }
            }

            while ( s1.size() > 0 && Integer.parseInt((s1.peek()).get("depth").toString()) > 1 ) {// clear stack
                JSONArray children = new JSONArray();
                int     lvl = Integer.parseInt((s1.peek()).get("depth").toString());
                while ( Integer.parseInt((s1.peek()).get("depth").toString()) == lvl ) {
                    s2.push(s1.pop());
                }
                while(s2.size() > 0 ) {
                    children.put(s2.pop());
                }
                j1 = s1.pop();
                j1.put("children", children);
                j1.remove("leaf");
                j1.put("leaf", false);
                s1.push(j1);
            }
        }
        catch( JSONException je) {
        }

        return new JSONArray(s1);
    }
}

java expert가 아니라 코드가 비효율적으로 구성되었을 수 있으나 일단 php에 없는 json함수와 tree 정렬 함수를 구현했다.

실행 결과는 tree 구조의 데이터를 json 형태로 보내게 된다.

실행 결과 예

{id:001,field0:root,parent_id:NULL,leaf:false,child:[{id:002,field0:'노드1',parent_id:001,leaf:true},{id:003,field0:'노드100',parent_id:001,leaf:true}]}

 

 

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다