2

I have a string: items[0].name that I want to apply to a JSON object: {"items":[{"name":"test"}]} which is contained in the variable test. I want to apply that string to the object in order to search it (test.items[0].name). I can only think of one way to do this: parse the square brackets and dots using my own function. Is there another way I can do this? Perhaps using eval? (Even though I'd LOVE to avoid that...)

For clarity: I have a JSON object, what is inside of it is really irrelevant. I need to be able to query the object like so: theobject.items[0], this is normal behaviour of a JSON object obviously. The issue is, that query string (ie. items[0]) is unknown - call it user input if you like - it is literally a string (var thisIsAString = "items[0]"). So, I need a way to append that query string to theobject in order for it to return the value at theobject.items[0]

2
  • Whaa? Update your question to include (1) Your original object, (2) What you are applying and (3) What the end result should look like. I'm really not following what you are trying to do here. Commented Nov 13, 2012 at 3:46
  • Note that there's no such thing as a JSON object. Commented Nov 13, 2012 at 5:33

2 Answers 2

8
function locate(obj, path) {

  path = path.split('.');
  var arrayPattern = /(.+)\[(\d+)\]/;
  for (var i = 0; i < path.length; i++) {
    var match = arrayPattern.exec(path[i]);
    if (match) {
      obj = obj[match[1]][parseInt(match[2])];
    } else {
      obj = obj[path[i]];
    }
  }

  return obj;
}

var name = locate(test, 'items[0].name');
Sign up to request clarification or add additional context in comments.

6 Comments

This looks like a viable solution. I'll give it a shot, thanks for your response.
Wow, nailed it. Thank you so much!
@iLoch Although it works, it's not recommended. You should avoid this problem at very beginning.
Yeah, I understand. The use is sort of complicated and I think this is an entirely acceptable answer given the circumstances. Will vote this up when I have enough points.
@iLoch Oh, noticed one thing, this code doesn't work with nested arrays. like item[1][2].
|
1

...JSON doesn't have objects, it's just a string. If you're dealing with an object (ie: you can reference it using dot/bracket notation) then it's just a JavaScript object/array...

So depending on what the deal is, if you're dealing with a 100% string:

'{"name":"string","array":[0,1,2]}'

Then you need to send it through JSON.parse;

var json_string = '{"name":"string","array":[0,1,2]}',
    js_obj = JSON.parse(json_string);

js_obj.name; // "string"
js_obj.array; // [0,1,2]
js_obj.array[1]; // 1

If it's not a string, and is indeed an object/array, with other objects/arrays inside, then you just need to go:

myObj.items[0].name = items[0].name;

If it IS a string, then .parse it, and use the parsed object to do exactly what I just did. If it needs to be a string again, to send to the server, then use JSON.stringify like:

var json_string = JSON.stringify(js_obj);

Now you've got your modified JSON string back.

If you need to support GhettoIE (IE < 8), then download json2.js from Douglas Crockford, and add that script on the page conditionally, if you can't find window.JSON.

5 Comments

Apparently I'm not being very clear. I don't need to parse the JSON. I need to parse the string that queries the object.
Right. Okay, that's more helpful. Are you engineering this yourself? If you have the option to change it, why not do so? If you don't have the option to change it, then you need to parse the string into tokens, and apply each token to your JS object, using bracket notation. For example, instead of using a string like "index[0]", you could query using arr = "index/0/children/5/name".split("/"); And in a while/for loop, obj = obj[ arr.shift() ]; (with appropriate checks to ensure a property exists, so you don't try to grab undefined[0]. This can be done with your initial example using...
@iLoch ...using RegEx to look for letters, numbers and underscores in any quantities (in a global RegEx) var arr = string.match(/[a-zA-Z0-9_]+/g), length = arr.length; while (length > 0) { obj = obj[arr.shift()]; if (!obj) { break; /*it's not there*/ } else { length -= 1; } }
This is a nice solution too, however I'd like to stick to JS syntax for clarity and simplicity. Thanks for your time! I've voted up your answers where applicable!
@iLoch For the record, the second solution (the .match(RegEx); while(...){} solution) will work for "one/2/three", but it will also work for "four-five-six" or "seven.eight[9]['__ten']", because all it does is makes an array of "words" which are separated by anything that isn't "word" (periods, quotes, commas, brackets, braces, et cetera). So as long as you're only using English letters, numbers and underscores in your variable names, it's going to work no matter how you break it up. And if you call a JS property using ["<KEY>"] JS doesn't care what it is - it just works.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.