简体   繁体   中英

Convert Javascript Object (incl. functions) to String

Hey, Im trying to convert specific javascript objects to a String. So far I'm working with json2.js. As soon as my Object contain functions, those functions are stripped. I need a way to convert functions too, any ideas?

There is a toString() method for functions in firefox, but how to make that work with json2.js?

Actually, I think it is possible and easy. At least when doing jsonP with nodeJS it works for me just fine, and it's demonstratable by the following fiddle. I did it by simply adding strings to a function:

var anyString = '';
var aFunction = function() { return true; };
var functionToText = anyString + aFunction;
console.log(functionToText);

here's the fiddle: http://jsfiddle.net/itsatony/VUZck/

Use String() function http://www.w3schools.com/jsref/jsref_string.asp

var f = function(a, b){
    return a + b; 
}
var str = String(f);

The short answer is that you cannot convert arbitrary JavaScript functions to strings. Period.

Some runtimes are kind enough to give you the string serialization of functions you defined but this is not required by the ECMAScript language specification. The "toString()" example you mentioned is a good example of why it cannot be done - that code is built in to the interpreter and in fact may not be implemented in JavaScript (but instead the language in which the runtime is implemented)! There are many other functions that may have the same constraints (eg constructors, built-ins, etc).

convert obj to str with below function:

function convert(obj) {
  let ret = "{";

  for (let k in obj) {
    let v = obj[k];

    if (typeof v === "function") {
      v = v.toString();
    } else if (v instanceof Array) {
      v = JSON.stringify(v);
    } else if (typeof v === "object") {
      v = convert(v);
    } else {
      v = `"${v}"`;
    }

    ret += `\n  ${k}: ${v},`;
  }

  ret += "\n}";

  return ret;
}

input

const input = {
  data: {
    a: "@a",
    b: ["a", 2]
  },

  rules: {
    fn1: function() {
      console.log(1);
    }
  }
}

const output = convert(input)

output

`{
  data: {
    a: "@a",
    b: ["a", 2]
  },
  rules: {
    fn1: function() {
      console.log(1);
    }
  }
}`

// typeof is String

Combining a few options

var aObj = { 
    v: 23,
    a: function() { 
        return true; 
    } 
};
var objStr = '';
for (var member in aObj) {
    objStr += (objStr ? ',\n': '')+
        member + ':' + aObj[member] + '';
}   

console.log('{\n'+
    objStr + '\n}');

JSFiddle

functionName.toString() will return a string of all the function code. I cut is after the name.

var funcString = CurrentButton.clickFunc.toString();
console.log("calling:" + funcString.substr(0, funcString.indexOf(")")-1));

 // utility for logging var log = function(s){ var d = document.getElementById('log'); var l = document.createElement('div'); l.innerHTML = (typeof s === 'object')?JSON.stringify(s):s; d.appendChild(l); } // wrapper function var obj = { 'x-keys': { 'z': function(e){console.log(e);}, 'a': [function(e){console.log('array',e);},1,2] }, 's': 'hey there', 'n': 100 }; log(obj); // convert the object to a string function otos(obj){ var rs = ''; var not_first = false; for(var k in obj){ if(not_first) rs += ','; if(typeof obj[k] === 'object'){ rs += '"'+k+'": {'+otos(obj[k])+'}'; } else if(typeof obj[k] === 'string' || typeof obj[k] === 'function'){ rs += '"'+k+'":"'+obj[k]+'"'; } else if(typeof obj[k] === 'number'){ rs += '"'+k+'":'+obj[k]+''; } else { // if it gets here then we need to add another else if to handle it console.log(typeof obj[k]); } not_first = true; } return rs; } // convert a string to object function stoo(str){ // we doing this recursively so after the first one it will be an object try{ var p_str = JSON.parse('{'+str+'}'); }catch(e){ var p_str = str;} var obj = {}; for(var i in p_str){ if(typeof p_str[i] === 'string'){ if(p_str[i].substring(0,8) === 'function'){ eval('obj[i] = ' + p_str[i] ); } else { obj[i] = p_str[i]; } } else if(typeof p_str[i] === 'object'){ obj[i] = stoo(p_str[i]); } } return obj; } // convert object to string var s = otos(obj); log(s); // convert string to object var original_obj = stoo(s); log(original_obj); log( original_obj['x-keys'].z('hey') ); log( original_obj['x-keys'].a[0]('hey') );
 <div id='log'></div>

I realize this is very old but I have a solution here

https://jsfiddle.net/stevenkaspar/qoghsxhd/2/

May not work for all cases but it is a good start

It will convert this into a string and then back into an object and you can run the functions

var obj = {
  'x-keys': {
    'z': function(e){console.log(e);},
    'a': [function(e){console.log('array',e);},1,2]
  },
  's': 'hey there',
  'n': 100
};

Just provide the object to this function. (Look for nested function) Here:

 function reviveJS(obj) { return JSON.parse(JSON.stringify(obj, function (k, v) { if (typeof v === 'function') { return '__fn__' + v; } return v; }), function (k, v) { if (typeof v === 'string' && v.indexOf('__fn__') !== -1) { return v; } return v; }); }

UPDATE

A slightly decent code than above which I was able to solve is here http://jsfiddle.net/shobhit_sharma/edxwf0at/

I made a improved version based on the @SIMDD function, to convert all types of objects to string.

Typescript code:

function anyToString(valueToConvert: unknown): string {
    if (valueToConvert === undefined || valueToConvert === null) {
        return valueToConvert === undefined ? "undefined" : "null";
    }
    if (typeof valueToConvert === "string") {
        return `'${valueToConvert}'`;
    }
    if (
        typeof valueToConvert === "number" ||
        typeof valueToConvert === "boolean" ||
        typeof valueToConvert === "function"
    ) {
        return valueToConvert.toString();
    }
    if (valueToConvert instanceof Array) {
        const stringfiedArray = valueToConvert
            .map(property => anyToString(property))
            .join(",");
        return `[${stringfiedArray}]`;
    }
    if (typeof valueToConvert === "object") {
        const stringfiedObject = Object.entries(valueToConvert)
            .map((entry: [string, unknown]) => {
                return `${entry[0]}: ${anyToString(entry[1])}`;
            })
            .join(",");
        return `{${stringfiedObject}}`;
    }
    return JSON.stringify(valueToConvert);
}

Vanilla Javascript code:

function anyToString(valueToConvert) {
    if (valueToConvert === undefined || valueToConvert === null) {
        return valueToConvert === undefined ? "undefined" : "null";
    }
    if (typeof valueToConvert === "string") {
        return `'${valueToConvert}'`;
    }
    if (typeof valueToConvert === "number" ||
        typeof valueToConvert === "boolean" ||
        typeof valueToConvert === "function") {
        return valueToConvert.toString();
    }
    if (valueToConvert instanceof Array) {
        const stringfiedArray = valueToConvert
            .map(property => anyToString(property))
            .join(",");
        return `[${stringfiedArray}]`;
    }
    if (typeof valueToConvert === "object") {
        const stringfiedObject = Object.entries(valueToConvert)
            .map((entry) => {
            return `${entry[0]}: ${anyToString(entry[1])}`;
        })
            .join(",");
        return `{${stringfiedObject}}`;
    }
    return JSON.stringify(valueToConvert);
}

ATENTION!

I am using the function Object.entries(), winch currently is a draft. So if you are not using Babel or typescript to transpile your code, you can replace it with a for loop or the Object.keys() method.

I took one of answers above, it worked fine, but didn't inlcude case then array includes function. So i modified it and it works fine for me.. Sharing the code.

 function convert(obj,ret="{") { function check(v) { if(typeof v === "function") v = v.toString() else if (typeof v === "object") v = convert(v) else if (typeof v == "boolean" || Number.isInteger(v)) v=v else v = `"${v}"` return v } if(obj instanceof Array) { ret="[" obj.forEach(v => { ret += check(v)+',' }); ret += "\n]" } else { for (let k in obj) { let v = obj[k]; ret += `\n ${k}: ${check(v)},`; } ret += "\n}"; } return ret }

So I was just testing your script on one of my project, and there's a problem with Object keys that contain special characters (like / or -).

You should consider wrapping theses keys with quotes.

return `"${entry[0]}" : ${anyToString(entry[1])}`;

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