Query-string encoding of a Javascript Object

前端 未结 30 2961
渐次进展
渐次进展 2020-11-22 00:23

Do you know a fast and simple way to encode a Javascript Object into a string that I can pass via a GET Request?

No jQuery, no

相关标签:
30条回答
  • 2020-11-22 00:58

    Just use URLSearchParams This works in all current browsers

    new URLSearchParams(object).toString()
    
    0 讨论(0)
  • 2020-11-22 01:01

    In ES7 you can write this in one line:

    const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
    
    0 讨论(0)
  • 2020-11-22 01:02

    jQuery has a function for this, jQuery.param(), if you're already using it you can use that: http://api.jquery.com/jquery.param/

    example:

    var params = { width:1680, height:1050 };
    var str = jQuery.param( params );
    

    str now contains width=1680&height=1050

    0 讨论(0)
  • 2020-11-22 01:02

    Here's a concise & recursive version with Object.entries. It handles arbitrarily nested arrays, but not nested objects. It also removes empty elements:

    const format = (k,v) => v !== null ? `${k}=${encodeURIComponent(v)}` : ''
    
    const to_qs = (obj) => {
        return [].concat(...Object.entries(obj)
                           .map(([k,v]) => Array.isArray(v) 
                              ? v.map(arr => to_qs({[k]:arr})) 
                              : format(k,v)))
               .filter(x => x)
               .join('&');
    }
    

    E.g.:

    let json = { 
        a: [1, 2, 3],
        b: [],              // omit b
        c: 1,
        d: "test&encoding", // uriencode
        e: [[4,5],[6,7]],   // flatten this
        f: null,            // omit nulls
        g: 0
    };
    
    let qs = to_qs(json)
    
    => "a=1&a=2&a=3&c=1&d=test%26encoding&e=4&e=5&e=6&e=7&g=0"
    
    0 讨论(0)
  • 2020-11-22 01:02

    The above answers fill not work if you have a lot of nested objects. Instead you can pick the function param from here - https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js It worked very well for me!

        var param = function (a) {
        var s = [], rbracket = /\[\]$/,
            isArray = function (obj) {
                return Object.prototype.toString.call(obj) === '[object Array]';
            }, add = function (k, v) {
                v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v;
                s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
            }, buildParams = function (prefix, obj) {
                var i, len, key;
    
                if (prefix) {
                    if (isArray(obj)) {
                        for (i = 0, len = obj.length; i < len; i++) {
                            if (rbracket.test(prefix)) {
                                add(prefix, obj[i]);
                            } else {
                                buildParams(prefix + '[' + (typeof obj[i] === 'object' ? i : '') + ']', obj[i]);
                            }
                        }
                    } else if (obj && String(obj) === '[object Object]') {
                        for (key in obj) {
                            buildParams(prefix + '[' + key + ']', obj[key]);
                        }
                    } else {
                        add(prefix, obj);
                    }
                } else if (isArray(obj)) {
                    for (i = 0, len = obj.length; i < len; i++) {
                        add(obj[i].name, obj[i].value);
                    }
                } else {
                    for (key in obj) {
                        buildParams(key, obj[key]);
                    }
                }
                return s;
            };
    
        return buildParams('', a).join('&').replace(/%20/g, '+');
    };
    
    0 讨论(0)
  • 2020-11-22 01:03

    If you want to convert a nested object recursively and the object may or may not contain arrays (and the arrays may contain objects or arrays, etc), then the solution gets a little more complex. This is my attempt.

    I've also added some options to choose if you want to record for each object member at what depth in the main object it sits, and to choose if you want to add a label to the members that come from converted arrays.

    Ideally you should test if the thing parameter really receives an object or array.

    function thingToString(thing,maxDepth,recordLevel,markArrays){
        //thing: object or array to be recursively serialized
        //maxDepth (int or false):
        // (int) how deep to go with converting objects/arrays within objs/arrays
        // (false) no limit to recursive objects/arrays within objects/arrays
        //recordLevel (boolean):
        //  true - insert "(level 1)" before transcript of members at level one (etc)
        //  false - just 
        //markArrays (boolean):
        //  insert text to indicate any members that came from arrays
        var result = "";
        if (maxDepth !== false && typeof maxDepth != 'number') {maxDepth = 3;}
        var runningDepth = 0;//Keeps track how deep we're into recursion
    
        //First prepare the function, so that it can call itself recursively
        function serializeAnything(thing){
            //Set path-finder values
            runningDepth += 1;
            if(recordLevel){result += "(level " + runningDepth + ")";}
    
            //First convert any arrays to object so they can be processed
            if (thing instanceof Array){
                var realObj = {};var key;
                if (markArrays) {realObj['type'] = "converted array";}
                for (var i = 0;i < thing.length;i++){
                    if (markArrays) {key = "a" + i;} else {key = i;}
                    realObj[key] = thing[i];
                }
                thing = realObj;
                console.log('converted one array to ' + typeof realObj);
                console.log(thing);
            }
    
            //Then deal with it
            for (var member in thing){
                if (typeof thing[member] == 'object' && runningDepth < maxDepth){
                    serializeAnything(thing[member]);
                    //When a sub-object/array is serialized, it will add one to
                    //running depth. But when we continue to this object/array's
                    //next sibling, the level must go back up by one
                    runningDepth -= 1;
                } else if (maxDepth !== false && runningDepth >= maxDepth) {
                    console.log('Reached bottom');
                } else 
                if (
                    typeof thing[member] == "string" || 
                    typeof thing[member] == 'boolean' ||
                    typeof thing[member] == 'number'
                ){
                    result += "(" + member + ": " + thing[member] + ") ";
                }  else {
                    result += "(" + member + ": [" + typeof thing[member] + " not supported]) ";
                }
            }
        }
        //Actually kick off the serialization
        serializeAnything(thing);
    
        return result;
    
    }
    
    0 讨论(0)
提交回复
热议问题