Converting an object to a string

后端 未结 30 1828
北荒
北荒 2020-11-22 03:29

How can I convert a JavaScript object into a string?

Example:

var o = {a:1, b:2}
console.log(o)
console.log(\'Item: \' + o)

Output:

相关标签:
30条回答
  • 2020-11-22 04:24

    Circular References

    By using below replacer we can produce less redundant JSON - if source object contains multi-references to some object, or contains circular references - then we reference it by special path-string (similar to JSONPath) - we use it as follows

    let s = JSON.stringify(obj, refReplacer());
    

    function refReplacer() {
      let m = new Map(), v= new Map(), init = null;
    
      return function(field, value) {
        let p= m.get(this) + (Array.isArray(this) ? `[${field}]` : '.' + field); 
        let isComplex= value===Object(value)
        
        if (isComplex) m.set(value, p);  
        
        let pp = v.get(value)||'';
        let path = p.replace(/undefined\.\.?/,'');
        let val = pp ? `#REF:${pp[0]=='[' ? '$':'$.'}${pp}` : value;
        
        !init ? (init=value) : (val===init ? val="#REF:$" : 0);
        if(!pp && isComplex) v.set(value, path);
       
        return val;
      }
    }
    
    
    
    
    // ---------------
    // TEST
    // ---------------
    
    // gen obj with duplicate references
    let a = { a1: 1, a2: 2 };
    let b = { b1: 3, b2: "4" };
    let obj = { o1: { o2:  a  }, b, a }; // duplicate reference
    a.a3 = [1,2,b];                      // circular reference
    b.b3 = a;                            // circular reference
    
    
    let s = JSON.stringify(obj, refReplacer(), 4);
    
    console.log(s);

    BONUS: and here is inverse function of such serialisation

    function parseRefJSON(json) {
      let objToPath = new Map();
      let pathToObj = new Map();
      let o = JSON.parse(json);
      
      let traverse = (parent, field) => {
        let obj = parent;
        let path = '#REF:$';
    
        if (field !== undefined) {
          obj = parent[field];
          path = objToPath.get(parent) + (Array.isArray(parent) ? `[${field}]` : `${field?'.'+field:''}`);
        }
    
        objToPath.set(obj, path);
        pathToObj.set(path, obj);
        
        let ref = pathToObj.get(obj);
        if (ref) parent[field] = ref;
    
        for (let f in obj) if (obj === Object(obj)) traverse(obj, f);
      }
      
      traverse(o);
      return o;
    }
    
    
    
    // ------------
    // TEST
    // ------------
    
    let s = `{
        "o1": {
            "o2": {
                "a1": 1,
                "a2": 2,
                "a3": [
                    1,
                    2,
                    {
                        "b1": 3,
                        "b2": "4",
                        "b3": "#REF:$.o1.o2"
                    }
                ]
            }
        },
        "b": "#REF:$.o1.o2.a3[2]",
        "a": "#REF:$.o1.o2"
    }`;
    
    console.log('Open Chrome console to see nested fields:');
    let obj = parseRefJSON(s);
    
    console.log(obj);

    0 讨论(0)
  • 2020-11-22 04:25
    /*
        This function is as JSON.Stringify (but if you has not in your js-engine you can use this)
        Params:
            obj - your object
            inc_ident - can be " " or "\t".
            show_types - show types of object or not
            ident - need for recoursion but you can not set this parameter.
    */
    function getAsText(obj, inc_ident, show_types, ident) {
        var res = "";
        if (!ident)
            ident = "";
        if (typeof(obj) == "string") {
            res += "\"" + obj + "\" ";
            res += (show_types == true) ? "/* typeobj: " + typeof(obj) + "*/" : "";
        } else if (typeof(obj) == "number" || typeof(obj) == "boolean") {
            res += obj;
            res += (show_types == true) ? "/* typeobj: " + typeof(obj) + "*/" : "";
        } else if (obj instanceof Array) {
            res += "[ ";
            res += show_types ? "/* typeobj: " + typeof(obj) + "*/" : "";
            res += "\r\n";
            var new_ident = ident + inc_ident;
            var arr = [];
            for(var key in obj) {
                arr.push(new_ident + getAsText(obj[key], inc_ident, show_types, new_ident));
            } 
            res += arr.join(",\r\n") + "\r\n";
            res += ident + "]";
        } else {
            var new_ident = ident + inc_ident;      
            res += "{ ";
            res += (show_types == true) ? "/* typeobj: " + typeof(obj) + "*/" : "";
            res += "\r\n";
            var arr = [];
            for(var key in obj) {
                arr.push(new_ident + '"' + key + "\" : " + getAsText(obj[key], inc_ident, show_types, new_ident));
            }
            res += arr.join(",\r\n") + "\r\n";
            res += ident + "}\r\n";
        } 
        return res;
    };
    

    example to use:

    var obj = {
        str : "hello",
        arr : ["1", "2", "3", 4],
    b : true,
        vobj : {
            str : "hello2"
        }
    }
    
    var ForReading = 1, ForWriting = 2;
    var fso = new ActiveXObject("Scripting.FileSystemObject")
    f1 = fso.OpenTextFile("your_object1.txt", ForWriting, true)
    f1.Write(getAsText(obj, "\t"));
    f1.Close();
    
    f2 = fso.OpenTextFile("your_object2.txt", ForWriting, true)
    f2.Write(getAsText(obj, "\t", true));
    f2.Close();
    

    your_object1.txt:

    { 
        "str" : "hello" ,
        "arr" : [ 
            "1" ,
            "2" ,
            "3" ,
            4
        ],
        "b" : true,
        "vobj" : { 
            "str" : "hello2" 
        }
    
    }
    

    your_object2.txt:

    { /* typeobj: object*/
        "str" : "hello" /* typeobj: string*/,
        "arr" : [ /* typeobj: object*/
            "1" /* typeobj: string*/,
            "2" /* typeobj: string*/,
            "3" /* typeobj: string*/,
            4/* typeobj: number*/
        ],
        "b" : true/* typeobj: boolean*/,
        "vobj" : { /* typeobj: object*/
            "str" : "hello2" /* typeobj: string*/
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 04:26

    1.

    JSON.stringify(o);
    

    Item: {"a":"1", "b":"2"}

    2.

    var o = {a:1, b:2};
    var b=[]; Object.keys(o).forEach(function(k){b.push(k+":"+o[k]);});
    b="{"+b.join(', ')+"}";
    console.log('Item: ' + b);
    

    Item: {a:1, b:2}

    0 讨论(0)
  • 2020-11-22 04:26
    var o = {a:1, b:2};
    
    o.toString=function(){
      return 'a='+this.a+', b='+this.b;
    };
    
    console.log(o);
    console.log('Item: ' + o);
    

    Since Javascript v1.0 works everywhere (even IE) this is a native approach and allows for a very costomised look of your object while debugging and in production https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/toString

    Usefull example

    var Ship=function(n,x,y){
      this.name = n;
      this.x = x;
      this.y = y;
    };
    Ship.prototype.toString=function(){
      return '"'+this.name+'" located at: x:'+this.x+' y:'+this.y;
    };
    
    alert([new Ship('Star Destroyer', 50.001, 53.201),
    new Ship('Millennium Falcon', 123.987, 287.543),
    new Ship('TIE fighter', 83.060, 102.523)].join('\n'));//now they can battle!
    //"Star Destroyer" located at: x:50.001 y:53.201
    //"Millennium Falcon" located at: x:123.987 y:287.543
    //"TIE fighter" located at: x:83.06 y:102.523
    

    Also, as a bonus

    function ISO8601Date(){
      return this.getFullYear()+'-'+(this.getMonth()+1)+'-'+this.getDate();
    }
    var d=new Date();
    d.toString=ISO8601Date;//demonstrates altering native object behaviour
    alert(d);
    //IE6   Fri Jul 29 04:21:26 UTC+1200 2016
    //FF&GC Fri Jul 29 2016 04:21:26 GMT+1200 (New Zealand Standard Time)
    //d.toString=ISO8601Date; 2016-7-29
    
    0 讨论(0)
  • 2020-11-22 04:27

    None of the solutions here worked for me. JSON.stringify seems to be what a lot of people say, but it cuts out functions and seems pretty broken for some objects and arrays I tried when testing it.

    I made my own solution which works in Chrome at least. Posting it here so anyone that looks this up on Google can find it.

    //Make an object a string that evaluates to an equivalent object
    //  Note that eval() seems tricky and sometimes you have to do
    //  something like eval("a = " + yourString), then use the value
    //  of a.
    //
    //  Also this leaves extra commas after everything, but JavaScript
    //  ignores them.
    function convertToText(obj) {
        //create an array that will later be joined into a string.
        var string = [];
    
        //is object
        //    Both arrays and objects seem to return "object"
        //    when typeof(obj) is applied to them. So instead
        //    I am checking to see if they have the property
        //    join, which normal objects don't have but
        //    arrays do.
        if (typeof(obj) == "object" && (obj.join == undefined)) {
            string.push("{");
            for (prop in obj) {
                string.push(prop, ": ", convertToText(obj[prop]), ",");
            };
            string.push("}");
    
        //is array
        } else if (typeof(obj) == "object" && !(obj.join == undefined)) {
            string.push("[")
            for(prop in obj) {
                string.push(convertToText(obj[prop]), ",");
            }
            string.push("]")
    
        //is function
        } else if (typeof(obj) == "function") {
            string.push(obj.toString())
    
        //all other values can be done with JSON.stringify
        } else {
            string.push(JSON.stringify(obj))
        }
    
        return string.join("")
    }
    

    EDIT: I know this code can be improved but just never got around to doing it. User andrey suggested an improvement here with the comment:

    Here is a little bit changed code, which can handle 'null' and 'undefined', and also do not add excessive commas.

    Use that at your own risk as I haven't verified it at all. Feel free to suggest any additional improvements as a comment.

    0 讨论(0)
  • 2020-11-22 04:28

    If you only care about strings, objects, and arrays:

    function objectToString (obj) {
            var str = '';
            var i=0;
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    if(typeof obj[key] == 'object')
                    {
                        if(obj[key] instanceof Array)
                        {
                            str+= key + ' : [ ';
                            for(var j=0;j<obj[key].length;j++)
                            {
                                if(typeof obj[key][j]=='object') {
                                    str += '{' + objectToString(obj[key][j]) + (j > 0 ? ',' : '') + '}';
                                }
                                else
                                {
                                    str += '\'' + obj[key][j] + '\'' + (j > 0 ? ',' : ''); //non objects would be represented as strings
                                }
                            }
                            str+= ']' + (i > 0 ? ',' : '')
                        }
                        else
                        {
                            str += key + ' : { ' + objectToString(obj[key]) + '} ' + (i > 0 ? ',' : '');
                        }
                    }
                    else {
                        str +=key + ':\'' + obj[key] + '\'' + (i > 0 ? ',' : '');
                    }
                    i++;
                }
            }
            return str;
        }
    
    0 讨论(0)
提交回复
热议问题