1

So I've got a JSON file that gets parsed into an object in Javascript. I know what you're thinking: lucky guy. The JSON is essentially a flow diagram in a big tree form. Here's tiny a sample of what I'm trying to achieve:

tree = {
    "options": [
        {
            "options": [
                {
                    "name": "target",
                },
            ],
        },
        {
            "options": [
                {
                    "link": "...?",
                },
            ],
        },
    ]
}

So in this example, I'll be deep in the second branch (where it says "link") and I'll want to be able to jump to the branch that contains "name": "target". This is JSON remember so it'll need to be a string (unless there's a native for linking?! is there?) but I don't know how best to format that.

As I see it, I've got at least a couple of options.

  1. I could search. If name was unique, I could scale the tree looking for elements until I found it. I've never done with with Javascript before but I expect it to be slow.

  2. I could use a navigation path like options:1:options:1 that describes each key for the path. Again, I've never done this but, assuming there are no errors, it would be a lot faster. How would you implement it?

Are there any other options available to me? What seems best? Is there a way to unpack this when JSON decoding, or is that a recipe for an infinite loop?

Oli
  • 235,628
  • 64
  • 220
  • 299
  • It's not clear what "resolve the dict object" means. – Pointy Aug 22 '13 at 13:10
  • Try and find a new project. LOL. You've got a pickle, for sure. This seems like a case for you to develop your own function that tears the tree branches down one by one and then acts upon them. It's JSON, so I don't know how much "speed" is actually going to be a factor. – DevlshOne Aug 22 '13 at 13:13
  • @Pointy I don't know how better to phrase it. I want to "get" the object that contains the name/value pair `"name":"target"`. Forgive me, I'm a Pythonista talking about Javascript so I'm bound to get some of the lingo incorrect. – Oli Aug 22 '13 at 13:15

1 Answers1

3

What about link: 'tree.options[0].options[0]' then eval(path.to.link)?

Following samples were tested with Chrome only. Same tree for all :

var tree = { level1: [{ key: 'value' }] };

No eval

function resolve(root, link) {
    return (new Function('root', 'return root.' + link + ';'))(root);
}

var value = resolve(tree, path.to.link);

Fallback to window

function resolve(root, link) {
    return (new Function(
        'root', 'return root.' + (link || root) + ';'
    ))(link ? root : window);
}

resolve(tree, 'level1[0].key'); // "value"
resolve('tree.level1[0].key'); // "value"

Catching errors

The try/catch block prevents broken links from throwing errors.

function resolve(root, path) {
    try {
        return (new Function('root', 'return root.' + path + ';'))(root);
    } catch (e) {}
}

resolve(tree, 'level1[0].key'); // "value"
resolve(tree, 'level1[1].key'); // undefined

Using custom path format

The good part here is that we can pass either an object or an array as root. Also note that we can replace the slash in path.split('/') with any char of our choice.

function resolve(root, path) {
    path = '["' + path.split('/').join('"]["') + '"]';
    return (new Function('root', 'return root' + path + ';'))(root);
}

resolve(tree.level1, '0/key'); // "value"
resolve(tree, 'level1/0/key'); // "value"
resolve(tree, 'level1/0'); // Object {key: "value"}
  • That's certainly interesting... Massively simplifies the coding side of things and security isn't really an issue here as I control the whole thing. – Oli Aug 22 '13 at 13:19
  • The without-`eval` version should definitely appease people who care enough but other than the arbitrary security risk with eval, what are the advantages of one method over the other? – Oli Aug 22 '13 at 13:29
  • 1
    Nothing in your case I think. I would say you have a better control on the origin of your path, for example you could pass copy of your tree to `resolve` : `resolve(treeCopy, path.to.link)`. –  Aug 22 '13 at 13:37
  • 1
    @downvoter I guess you downvoted for the dynamic code evaluation. Fear! Fear! Well, this is not necessarily the evil as long as you maintain control over the input : http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/. –  Nov 28 '13 at 07:04
  • Alternatives to dynamic code evaluation can be found here : http://stackoverflow.com/q/6491463/1636522. –  Mar 05 '14 at 07:09