'JSON'에 해당되는 글 2

  1. 2006/10/28 zziuni JSON <-> Text 함수
  2. 2006/05/11 zziuni asp위한 JSON Parser 구현(prototype.js기반)

JSON <-> Text 함수

WebDev/Javascript | 2006/10/28 00:57 | zziuni
Ajax쪽을 손대면 댈 수록 JSON의 유용함은 말로 다 할 수가 없다.
JSON 이라는게 말은 멋드러지지만 사실상 Javascript에서 객체(Object)선언을 해서 쓰고 있는것이 바로 JSON이다. (JSON을 잘 모른다면 여기로! 언어 중립적이라고 하는데, 내가 보이엔 자바스크립트의 객체, 그 자체다.)
XML같은 경우 Javascript에서 호출은 쉽지만 컨트롤 하기가 만만치 않은데, 이럴때 서버와의 송수신을 JSON으로 하면 트래픽도 줄이고 훨씬 컨트롤 하기가 용의하다.
혹은, 수신을 XML DOM으로 했다 하더라도, DOM -> JSON 로 변환을 하면 보다 쉽게 작업이 가능하다.
Yusuke Kawasaki 가 제작한 jkl-parsexml.js 를 사용하거나 Prototype.js에 jkl-parsexml.js 의 JSON 로직을 추가한 걸 사용하면 쉽게 JSON을 사용할 수 있다.

어쨌든 할 이야기는 그게 아니고...
근데, 오늘 자료를 찾다가 JSON 영문 소개페이지에서 JSON in Javascirpt 를 찾았다.
분명 봤던 페이진데, 가장하단에 링크를 못봤던거 같다. 여기엔 js 소스가 하나 걸려있는데,
JSONText를 Object로, Object를 JSONText로 리턴해주는 메소드를 제공한다.
(이 페이지 내용이 그 소스에 대한 내용인데, 한마디로 '어? 영어내?' 하고 안읽었다는 말이지.. ㅡ ㅡ)
만들어진 JSON객체의 하위노드명(적절한 표현이.. ㅡ ㅡa) 몰라 곤란한경우가  있었는데, 한방에 해결됬다. 어떤경우냐고?
ASP.NET에서 사용하는 Ajax.NET은 .NET의 DataSet을 Javascript로 return이 가능하다. 처음에는 무척 놀랬다. 그게 가능하단 말야???
하지만 실은 다음과 같은 형태의 JSON객체를 반환한다.

ds.Tablse[].Rows[].ColumnName

위와 같은 객체가 ds란 Javascript 변수에 달랑 담기면, 값을 조회하기위해 DB Table의 컬럼명을 다시 조회해야 한다. 아님 다음처럼 쓰던가..

ds.Tablse[0].Rows[0][2]

이럴때 위 소스에서 제공하는 Object.toJSONString() 이 도움이 된다.





크리에이티브 커먼즈 라이센스
Creative Commons License
2006/10/28 00:57 2006/10/28 00:57

asp에는 JSON의 서버쪽 모듈이 없다.
그 이유든 아니든 XML로 데이터 통신을 할일이 늘고 있고, 모두들 나름대로 XML를 컨트롤 하는 함수를 만들어서 쓰고 있다.
ASP쪽에선 나름대로 노하우를 쌓아가고 있지만,
Ajax에서는 XMLHttpRequest 로 XMLDOM를 반한받은후 컨트롤 하기가 여간 버겨운것이 아니였다.
(javascript가 익숙하지 않은것이 가장큰 이유겠지만. )
서버단에서 부터 JSON으로 보낼 수 있다면, 더 좋겠지만, ASP에서는 아직 그런 모듈이 없기때문에,
통신은 XML로 하고 반환받은 XML DOM를 JSON으로 변환만 할 수 있어도 Ajax개발을 할때 많은 도움이 될것 같다.
그래서 현재 프래임워크로 선택한 Prototype.js기반으로 작동하는 JSONParser가 필요했고,
Yusuke Kawasaki 가 제작한 jkl-parsexml.js를 참고하여 Prototype.js기반의 JSONParser Object를 추가했다.  (말이 참고지... 따왔다. ㅡ ㅡ;;)

사용법은 다음과 같다.

var AFUrl = "./test.xml"
var AvatarFD ;
//ajax XML 로드
function loadAjaxXML(url, pars, fncSuccess, fncFailure){
var myAjax = new Ajax.Request(
    url,
    {
      method: 'get',
      parameters: pars,
      onSuccess: fncSuccess,
      onFailure: fncFailure
    });
}
function setAvatarFoundation(originalRequest){
AvatarFD = new JSONParser(originalRequest);
var json = AvatarFD.data;
alert("json.Avatar.Foundation.IMGPath=" + json.Avatar.Foundation.FullItem.ItemName)
 }
function falseLoad(){alert('XML Load Error');}
loadAjaxXML(AFUrl, '', setAvatarFoundation, falseLoad)

객체 JSONParser에 할당된 originalRequest는 Prototype.js에서 Ajax.Request를 사용할때 반환되는 원본 Oject다. 이걸 인자로 하여 객체를 만들고, 메소드 data()를 써주면, XML은 JSON으로 파싱된되고,샘플의  json.Avatar.Foundation.FullItem.ItemName처럼 XML이 노드명을 Object Name으로 하여 하위접근이 가능해진다.


다음은 Prototype.js에 추가된 소스다. 부족한 샘플과 추가 설명은 다음에...

//==============================================================================
JSONParser = Class.create();
Object.extend(JSONParser.prototype, {
  //initialize
initialize: function(req) {
 this.req = req;
 if ( ! this.req ) return;
 if ( this.req.responseXML ) {
  this.root =  this.req.responseXML.documentElement;    // XMLHTTPRequest
 } else {
 
  this.root =  this.req.documentElement;                // IXMLDOMDocument
 }
 this.data = this.parseDocument(this.root);
},
parseDocument: function(root){
 
 var ret = this.parseElement(root);
 var json = {};
 json[root.nodeName] = ret;                      // root nodeName
 
 return json;

}
 
});

// ================================================================
//  convert from DOM Element to JavaScript Object
//  method: parseElement( element )
JSONParser.prototype.parseElement = function(elem){

   //  COMMENT_NODE

   if ( elem.nodeType == 7 ) {
       return;
   }
   //  TEXT_NODE CDATA_SECTION_NODE
   if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
       var bool = elem.nodeValue.match( /[^\x00-\x20]/ ); // for Safari
       if ( bool == null ) return;     // ignore white spaces
       return elem.nodeValue;
   }
   var retval;
   var cnt = {};
   //  parse attributes

   if ( elem.attributes && elem.attributes.length ) {
       retval = {};
       for ( var i=0; i<elem.attributes.length; i++ ) {
           var key = elem.attributes[i].nodeName;
           if ( typeof(key) != "string" ) continue;
           var val = elem.attributes[i].nodeValue;
           if ( ! val ) continue;
           if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
           cnt[key] ++;
           this.addNode( retval, key, cnt[key], val );
       }
   }
   //  parse child nodes (recursive)
   if ( elem.childNodes && elem.childNodes.length ) {
 
       var textonly = true;
       if ( retval ) textonly = false;        
       for ( var i=0; i<elem.childNodes.length && textonly; i++ ) {
           var ntype = elem.childNodes[i].nodeType;
           if ( ntype == 3 || ntype == 4 ) continue;
           textonly = false;
       }
       if ( textonly ) {
           if ( ! retval ) retval = "";
           for ( var i=0; i<elem.childNodes.length; i++ ) {
               retval += elem.childNodes[i].nodeValue;
           }
       } else {
           if ( ! retval ) retval = {};
           for ( var i=0; i<elem.childNodes.length; i++ ) {
               var key = elem.childNodes[i].nodeName;
               if ( typeof(key) != "string" ){ continue;}
               var val = this.parseElement( elem.childNodes[i] );
               if ( ! val ){ continue;}
               if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
               cnt[key] ++;
   
               this.addNode( retval, key, cnt[key], val );
           }
       }
   }
   return retval;
}
// ================================================================
//  method: addNode( hash, key, count, value )
JSONParser.prototype.addNode = function ( hash, key, cnts, val ) {
if ( cnts == 1 ) {                      // 1st sibling
 hash[key] = val;
} else if ( cnts == 2 ) {               // 2nd sibling
 hash[key] = [ hash[key], val ];
} else {                                // 3rd sibling and more
 hash[key][hash[key].length] = val;
}
};
JSONParser.nodeType = [
   "",
   "ELEMENT_NODE",                 // 1
   "ATTRIBUTE_NODE",               // 2
   "TEXT_NODE",                    // 3
   "CDATA_SECTION_NODE",           // 4
   "ENTITY_REFERENCE_NODE",        // 5
   "ENTITY_NODE",                  // 6
   "PROCESSING_INSTRUCTION_NODE",  // 7
   "COMMENT_NODE",                 // 8
   "DOCUMENT_NODE",                // 9
   "DOCUMENT_TYPE_NODE",           // 10
   "DOCUMENT_FRAGMENT_NODE",       // 11
   "NOTATION_NODE"                 // 12
];
크리에이티브 커먼즈 라이센스
Creative Commons License
2006/05/11 21:13 2006/05/11 21:13