简体   繁体   中英

How can I convert json to indented text tree efficiently?

Given a JSON like this:

{
    Normalize: {},
    Typography: {},
    'Flex-grid': {},
    Elements: {},
    Forms: {},
    Navigation: {
        Links: {},
        Menus: {}
    },
    Accessibility: {},
    Alignments: {},
    Clearings: {},
    Widgets: {},
    Content: {
        'Posts-and-pages': {},
        Comments: {}
    },
    'Infinite-scroll': {},
    Media: {
        Captions: {},
        Galleries: {}
    }
}

I want to generate an indented plain text like this:

# Normalize
# Typography
# Flex grid
# Elements
# Forms
# Navigation
    ## Links
    ## Menus
# Accessibility
# Alignments
# Clearings
# Widgets
# Content
    ## Posts and pages
    ## Comments
# Infinite scroll
# Media
    ## Captions
    ## Galleries

I have come up with some quick and dirty code (I'm a javascript beginner) to achieve this. When I run the code, it seems very slow. What can I do to make this faster and more efficient?

function jsonToIndentedText(json) {
    var text = JSON.stringify(json, null, '\t');

    var indentedText = [];

    var lines = text.split('\n');

    lines.forEach(function(line) {
        if ('{' == line || '{' == line || '' == line) {
            return;
        }

        var textNow = line.replace(/"/gi, '').replace(/:[\s | \S]*$/i, '');

        if (textNow.search("}") < 0) {
            textNowArr = textNow.split(/\t/gi);
            level = textNowArr.length - 1;
            var indents = '';
            var hashes = '#';
            for (var i = 1; i < level; i++) {
                indents += '\t';
                hashes += '#';
            }
            indentedText.push(indents + hashes + ' ' + textNow.replace(/\t/gi, '').replace(/-/gi,' '));
        }

    });
    return indentedText.join('\n');
}

Here's my jsfiddle: https://jsfiddle.net/94t4dyag/1/

I don't think you should convert the object to a JSON string and then manually parse the string using javascript -- especially when the object itself represents the JSON string already.

Try something like this:

function prettify(obj){

    return recurse(0, obj);        

    function recurse(level, obj){
        var result = "";
        foreach(var prop in obj)
        if(obj.hasOwnProperty(prop))
        {
            result += printIndents(level);//TODO write this
            result += prop + "\n"; 
            result += recurse(level + 1, obj[prop]);
        }

        return result;
    }
}

I suggest to use the object itself, because you do not need string operations for it.

This proposal uses a function for recursive call with an object as parameter and the actual depth level.

Inside of the function get all keys from the object and iterates them. Then a check is made if the value is an object or not. With an object, the function is called again with the acual object and an increased level.

If a value is found, then the value is added to the result string.

 function print(object, level) { var SPACER = ' ', NEWLINE = '\\n' result = ''; level = level || 0; Object.keys(object).forEach(function (key) { var i = level; while (i--) { result += SPACER; } if (typeof object[key] === 'object' && object[key] !== null) { result += key + NEWLINE; result += print(object[key], level + 1); return; } result += key + ': ' + object[key] + NEWLINE; }); return result; } var data = { Normalize: { somekey: 1 }, Typography: { anotherkey: 2 }, 'Flex-grid': {}, Elements: {}, Forms: {}, Navigation: { Links: {}, Menus: {} }, Accessibility: {}, Alignments: {}, Clearings: {}, Widgets: {}, Content: { 'Posts-and-pages': {}, Comments: {} }, 'Infinite-scroll': {}, Media: { Captions: {}, Galleries: {} } }; document.getElementById('pre').innerHTML = print(data); 
 <pre id="pre"></pre> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM