0

I have some json : data.

I have a string build that looks like this: sections.1.subsections.0.items.0.citation.paragraph

What I need to do is manipulate that string to be able to access that value in data. So turn it into something usable: data['sections'][1]['subsections'][0]['items'][0]['citation']['paragraph']

And then use it to change that value in data. So: data['sections'][1]['subsections'][0]['items'][0]['citation']['paragraph'] = 'new value'

I can split the original string on the . and I think that gets me somewhere but I'm not at all sure how to then re-use the parts to allow me access to that value in data.

Thanks!

5
  • So convert dot notation to array notation? Commented Apr 17, 2015 at 17:25
  • but the dot notation is a string Commented Apr 17, 2015 at 17:26
  • Could you explain why sections.1.subsections.0.items.0.citation.paragraph is a string? if you used variables then sections[1].subsections[0].items[0].citation.paragraph would give you what you want Commented Apr 17, 2015 at 17:26
  • i'm building that string from another json object that has a change set. so i'm saving the path to the change as a string; I need that path to be able to apply the changes back to the original object. @ShanRobertson - use variables? I think that's what I'm trying to do with the split part. Commented Apr 17, 2015 at 17:37
  • Ya warlocks answer is what you'll have to do Commented Apr 17, 2015 at 17:56

1 Answer 1

3

I'm still not quite sure why you're handling the JSON in this fashion but if it has to be done this way, then you'll need to use recursion to access the data. Assuming I mapped your object correctly, the example below should provide you with a method for doing this:

var data = {
    sections: [
        {
            subsections: []    
        },
        {
            subsections: [
                {
                    items: [
                        {
                            citation: {
                                paragraph: "Citation by Warlock"    
                            }
                        }
                    ]
                }
            ]
        }
    ]
};

var string = "sections.1.subsections.0.items.0.citation.paragraph",
    parts = string.split('.');

function getValue(tree, index) {
    if(index < (parts.length - 1)) {
        return getValue(tree[parts[index]], index + 1);
    } else {
        return tree[parts[index]];
    }
}

function setValue(tree, index, newValue) {
    if(index < (parts.length - 1)) {
        setValue(tree[parts[index]], index + 1, newValue);
    } else {
        tree[parts[index]] = newValue;    
    }
}

alert(getValue(data, 0));
setValue(data, 0, "New Citation By Warlock");
alert(getValue(data, 0));

The idea is that the getValue(...); function steps one layer deep into your JSON and then recursively calls itself. This allows the data to be accessed one step at a time until the last part is retrieved. The value is then returned via the recursion in all the previous function calls.

The same idea is true for setting the value. The setValue(...); function steps into the JSON one layer at a time passing the new value to set until it's reached the last nested layer. The value is then set for the specified property.

EDIT:

A better implementation would be to pass the parts array into the getValue(...); and setValue(...); function to eliminate external dependencies. Then, within the function shift the array's data values to step through the nested layers. This eliminates the need for index tracking based on the original array's values:

var data = {
    sections: [
        {
            subsections: []    
        },
        {
            subsections: [
                {
                    items: [
                        {
                            citation: {
                                paragraph: "Citation by Warlock"    
                            }
                        }
                    ]
                }
            ]
        }
    ]
};


var string = "sections.1.subsections.0.items.0.citation.paragraph",
    parts = string.split('.');

function getValue(temp, tree) {
    if(temp.length > 1) {
        tree = tree[temp[0]];
        temp.shift();
        return getValue(temp, tree);
    } else {
        return tree[temp[0]];
    }
}

function setValue(temp, tree, newValue) {
    if(temp.length > 1) {
        tree = tree[temp[0]];
        temp.shift();
        setValue(temp, tree, newValue);
    } else {
        tree[temp[0]] = newValue;    
    }
}

alert(getValue(parts, data));
setValue(parts, data, "New Citation By Warlock");
alert(getValue(parts, data));

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @War10ck! This did it. There may be a better way to handle it all but this is what I needed for now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.