Search code examples
javascriptnode.jshttpurlcasting

casting a string as a JavaScript object


In JavaScript, I can cast convert numbers to strings and vice versa, but there is no way to cast convert a string to an object

num = 1
str = '1'

num_as_str = String(num) // "1"
str_as_num = Number(str) // 1

str = '{ a: "foo", b: "bar", c: { a: "foo", b: "bar" }}'
str_as_obj = Object(str) // does not exist

Assuming my string (to be cast converted as an object) is predictable and relatively simply, what is the best way to achieve the above other than using a regexp to parse out the indiv key-val pairs? Suggestions welcome

background: I want to do the above because I want to be able to pass and receive complex values in a URL. For example, /index.html?q=within({r:20, u: "kms", lat: 35.32, lng: -22.0132}) (of course, I will URL encode/decode properly along the way). Fwiw, the node querystring module wipes out anything other strings, numbers, booleans and arrays by coercing them to empty strings.

background2: of course, I know about JSON.parse and JSON.stringify, but I have a user-submitted URL querystring param that is most easily transmitted as an object, except a querystring cannot deal with an object. That is what I am trying to find a way around.


Solution

  • I want to do the above because I want to be able to pass and receive complex values in a URL

    Use JSON, not a JavaScript object initializer.

    of course, I know about JSON.parse and JSON.stringify, but I have a user-submitted URL querystring param that is most easily transmitted as an object

    The JSON version ({"a":"foo","b":"bar","c":{"a":"foo","b":"bar"}}) is just as easily transmitted. It URI-encodes to

     %7B%22a%22%3A%22foo%22%2C%22b%22%3A%22bar%22%2C%22c%22%3A%7B%22a%22%3A%22foo%22%2C%22b%22%3A%22bar%22%7D%7D
    

    vs. your original:

    %7Ba%3A%22foo%22%2Cb%3A%22bar%22%2Cc%3A%7Ba%3A%22foo%22%2Cb%3A%22bar%22%7D%7D
    

    Not much difference. (Yes, it's slightly longer.) And it has the advantage that JSON.parse is a built-in feature that doesn't allow arbitrary code execution.


    If you must use the object literal string instead, you have to parse that string. There are two built-in ways to do it (eval and new Function), but unfortunately both of them execute the code, and don't limit what the code can be — you can't say, for instance, "only allow an object literal and no function calls."

    It sounds like it's entirely possible that User A will be specifying the string and then you'll be evaluating it when showing a page to User B. If so, you can't use eval or new Function without exposing User B to risks from malicious code.

    So you'll need to use a parser like Esprima or similar instead. You could probably also adapt Crockford's original JSON parser to allow unquoted property names.

    So really, JSON is the way to go, but if you really don't want JSON, use a parser that doesn't allow arbitrary code execution.