代码改变世界

1、利用json2html.js处理json数据

2015-11-05 15:09  怡红院丿无痕  阅读(655)  评论(0编辑  收藏  举报

1、json2html.js的代码

//Copyright (c) 2013 Crystalline Technologies
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'),
//  to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
//  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

var json2html = {
    
    /* ---------------------------------------- Public Methods ------------------------------------------------ */
    'transform': function(json,transform,_options) {
        
        //create the default output
        var out = {'events':[],'html':''};
        
        //default options (by default we don't allow events)
        var options = {
            'events':false
        };
        
        //extend the options
        options = json2html._extend(options,_options);

        //Make sure we have a transform & json object
        if( transform !== undefined || json !== undefined ) {

            //Normalize strings to JSON objects if necessary
            var obj = typeof json === 'string' ? JSON.parse(json) : json;
            
            //Transform the object (using the options)
            out = json2html._transform(obj, transform, options);
        }
        
        //determine if we need the events
        // otherwise return just the html string
        if(options.events) return(out);
            else return( out.html );
    },
    
    /* ---------------------------------------- Private Methods ------------------------------------------------ */
    
    //Extend options
    '_extend':function(obj1,obj2){
        var obj3 = {};
        for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
        for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
        return obj3;
    },
    
    //Append results
    '_append':function(obj1,obj2) {
        var out = {'html':'','event':[]};
        if(typeof obj1 !== 'undefined' && typeof obj2 !== 'undefined') {
            out.html = obj1.html + obj2.html;

            out.events = obj1.events.concat(obj2.events);
        }

        return(out);
    },

    //isArray (fix for IE prior to 9)
    '_isArray':function(obj) {
        return Object.prototype.toString.call(obj) === '[object Array]';
    },
    
    //Transform object
    '_transform':function(json, transform, options) {
        
        var elements = {'events':[],'html':''};
        
        //Determine the type of this object
        if(json2html._isArray(json)) {
            
            //Itterrate through the array and add it to the elements array
            var len=json.length;
            for(var j=0;j<len;++j) {    
                //Apply the transform to this object and append it to the results
                elements = json2html._append(elements,json2html._apply(json[j], transform, j, options));
            }

        } else if(typeof json === 'object') {

            //Apply the transform to this object and append it to the results
            elements = json2html._append(elements,json2html._apply(json, transform, undefined, options));
        }

        //Return the resulting elements
        return(elements);        
    },

    //Apply the transform at the second level
    '_apply':function(obj, transform, index, options) {

        var element = {'events':[],'html':''};
        
        //Itterate through the transform and create html as needed
        if(json2html._isArray(transform)) {
            
            var t_len = transform.length;
            for(var t=0; t < t_len; ++t) {
                //transform the object and append it to the output
                element = json2html._append(element,json2html._apply(obj, transform[t], index, options));
            }

        } else if(typeof transform === 'object') {

            //Get the tag element of this transform
            if( transform.tag !== undefined ) {

                var tag = json2html._getValue(obj,transform,'tag',index);

                //Create a new element
                element.html += '<' + tag;

                //Create a new object for the children
                var children = {'events':[],'html':''};
                
                //innerHTML
                var html;

                //Look into the properties of this transform
                for (var key in transform) {

                    switch(key) {
                        case 'tag':
                            //Do nothing as we have already created the element from the tag
                        break;

                        case 'children':
                            //Add the children
                            if(json2html._isArray(transform.children)) {

                                //Apply the transform to the children
                                children = json2html._append(children,json2html._apply(obj, transform.children, index, options));
                            } else if(typeof transform.children === 'function') {
                                
                                //Get the result from the function
                                var temp = transform.children.call(obj, obj, index);

                                //Make sure we have an object result with the props
                                // html (string), events (array)
                                // OR a string (then just append it to the children
                                if(typeof temp === 'object') {
                                    //make sure this object is a valid json2html response object
                                    if(temp.html !== undefined && temp.events !== undefined) children = json2html._append(children,temp);
                                } else if(typeof temp === 'string') {

                                    //append the result directly to the html of the children
                                    children.html += temp;
                                }
                            }
                        break;

                        case 'html':
                            //Create the html attribute for this element
                            html = json2html._getValue(obj,transform,'html',index);
                        break;

                        default:
                            //Add the property as a attribute if it's not a key one
                            var isEvent = false;
                            
                            //Check if the first two characters are 'on' then this is an event
                            if( key.length > 2 )
                                if(key.substring(0,2).toLowerCase() == 'on') {
                                    
                                    //Determine if we should add events
                                    if(options.events) {

                                        //if so then setup the event data
                                        var data = {
                                            'action':transform[key],
                                            'obj':obj,
                                            'data':options.eventData,
                                            'index':index
                                        };
                                        
                                        //create a new id for this event
                                        var id = json2html._guid();

                                        //append the new event to this elements events
                                        element.events[element.events.length] = {'id':id,'type':key.substring(2),'data':data};

                                        //Insert temporary event property (json2html-event-id) into the element
                                        element.html += " json2html-event-id-"+key.substring(2)+"='" + id + "'";
                                    }
                                    //this is an event
                                    isEvent = true;
                                }

                            //If this wasn't an event AND we actually have a value then add it as a property
                            if( !isEvent){
                                //Get the value
                                var val = json2html._getValue(obj, transform, key, index);
                                
                                //Make sure we have a value
                                if(val !== undefined) {
                                    var out;
                                    
                                    //Determine the output type of this value (wrap with quotes)
                                    if(typeof val === 'string') out = '"' + val.replace(/"/g, '&quot;') + '"';
                                    else out = val;
                                    
                                    //creat the name value pair
                                    element.html += ' ' + key + '=' + out;
                                }
                            }
                        break;
                    }
                }

                //close the opening tag
                element.html += '>';
                
                //add the innerHTML (if we have any)
                if(html) element.html += html;

                //add the children (if we have any)
                element = json2html._append(element,children);

                //add the closing tag
                element.html += '</' + tag + '>';
            }
        }
        
        //Return the output object
        return(element);
    },

    //Get a new GUID (used by events)
    '_guid':function() {
        var S4 = function() {
           return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
        };
        return (S4()+S4()+"-"+S4()+S4()+"-"+S4()+S4());
    },

    //Get the html value of the object
    '_getValue':function(obj, transform, key,index) {
        
        var out = '';
        
        var val = transform[key];
        var type = typeof val;
        
        if (type === 'function') {
            return(val.call(obj,obj,index));
        } else if (type === 'string') {
            var _tokenizer = new json2html._tokenizer([
                /\$\{([^\}\{]+)\}/
            ],function( src, real, re ){
                return real ? src.replace(re,function(all,name){
                    
                    //Split the string into it's seperate components
                    var components = name.split('.');

                    //Set the object we use to query for this name to be the original object
                    var useObj = obj;

                    //Output value
                    var outVal = '';
                    
                    //Parse the object components
                    var c_len = components.length;
                    for (var i=0;i<c_len;++i) {

                        if( components[i].length > 0 ) {

                            var newObj = useObj[components[i]];
                            useObj = newObj;
                            if(useObj === null || useObj === undefined) break;
                        }
                    }
                    
                    //As long as we have an object to use then set the out
                    if(useObj !== null && useObj !== undefined) outVal = useObj;

                    return(outVal);
                }) : src;
            });
            
            out = _tokenizer.parse(val).join('');
        } else {
            out = val;
        }

        return(out);
    },
    
    //Tokenizer
    '_tokenizer':function( tokenizers, doBuild ){

        if( !(this instanceof json2html._tokenizer ) )
            return new json2html._tokenizer( tokenizers, doBuild );
            
        this.tokenizers = tokenizers.splice ? tokenizers : [tokenizers];
        if( doBuild )
            this.doBuild = doBuild;

        this.parse = function( src ){
            this.src = src;
            this.ended = false;
            this.tokens = [ ];
            do {
                this.next();
            } while( !this.ended );
            return this.tokens;
        };
        
        this.build = function( src, real ){
            if( src )
                this.tokens.push(
                    !this.doBuild ? src :
                    this.doBuild(src,real,this.tkn)
                );    
        };

        this.next = function(){
            var self = this,
                plain;
                
            self.findMin();
            plain = self.src.slice(0, self.min);
            
            self.build( plain, false );
                
            self.src = self.src.slice(self.min).replace(self.tkn,function( all ){
                self.build(all, true);
                return '';
            });
            
            if( !self.src )
                self.ended = true;
        };

        this.findMin = function(){
            var self = this, i=0, tkn, idx;
            self.min = -1;
            self.tkn = '';
            
            while(( tkn = self.tokenizers[i++]) !== undefined ){
                idx = self.src[tkn.test?'search':'indexOf'](tkn);
                if( idx != -1 && (self.min == -1 || idx < self.min )){
                    self.tkn = tkn;
                    self.min = idx;
                }
            }
            if( self.min == -1 )
                self.min = self.src.length;
        };
    }
};

 

2、测试代码

    2.1  example.escape.js

(function() {
    //Test the handling of quoted strings 
    var test_data = {"test1":"'single-quoted'", "test2":"\"double-quoted\""};
    var test_data2 = {"test1":"<b>escape HTML test</b>", "test2":"<b>escape HTML test</b>"};

    var transform = [
            {"tag":"input", "html":"", "value":"${test1}"},
            {"tag":"input", "html":"", "value":"${test2}"},
            {"tag":"textarea", "html":"${test1}"},
            {"tag":"textarea", "html":"${test2}"},
        ];

        
    var html = json2html.transform(test_data, transform);
    var html2 = json2html.transform(test_data2, transform);

    document.write('<h1>Escape Quotes Test</h1>'+ html);
    document.write('<h1>Escape HTML Test</h1>'+ html2);
    
})();

    2.2  example.nested.js

    
    //Test nested dynamic children 
    // calls json2html recusively(递归的)
    var nested = {"Name": "Parent", "Children": [{"Name": "Child1"}, {"Name": "Child1"}]};

    var transform_parent = [
            {"tag":"span", "html":"${Name}"},
            {"tag":"ul", children:function(){return(json2html.transform(this.Children, transform_child));}}
        ];

    var transform_child = 
            {"tag":"li", children:[
                {"tag": "b", "html":"${Name}"}
            ]};
        
    var html = json2html.transform(nested,transform_parent);

    document.write('<h1>Nested Test</h1>'+ html);

    2.2  example.shorthand.js

     

    //Test the short hand notation 
    // as well as the direct reference via this
    var movies = [
        { "Name": "The Red Violin", "ReleaseYear": "1998" },
        { "Name": "The blue Violin", "ReleaseYear": "1998" },
        { "Name": "The yellow Violin", "ReleaseYear": "1998" },
        { "Name": "The purple Violin", "ReleaseYear": "1998" },
        { "Name": "The orange Violin", "ReleaseYear": "1998" }
    ];

    var transform_shortHand = 
            {"tag": "li", "children": [
                {"tag":"b", "html":"${Name}"},
                {"tag":"span", "html":"${ReleaseYear}"}            
            ]};

    var transform_longHand = 
            {"tag": "li", children: [
                {"tag": "b", "html": function(){return(this.Name);}},
                {"tag": "span", "html": function(){return(this.ReleaseYear);}}
            ]};
        
    var html1 = json2html.transform(movies,transform_shortHand);
    
    var html2 = json2html.transform(movies,transform_longHand);
    
    document.write('<h1>Shorthand Test</h1>'+ html1 + '<br><br>' + html2);
    

 

  3、测试页面

       

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
    <title> json2html examples </title>

    <!-- Add JSON2HTML -->
    <script type="text/javascript" src="json2html.js"></script>
    <script type="text/javascript" src="jquery.js"></script>
    <script>
    
    $(function(){
    
        
    });
    
    
    </script>
    
 </head>
 <body>
    
 </body>
</html>