JavaScript issue: Shallow copy does not reflect updates in nested JSON object

Within my coding project, I came across a nested JSON object that looks like this:

var jsonObj = 
{ "level1" : 
      { "status" : true,
        "level2" : {} // with the potential to extend further to level 3, 4, and beyond
       }
}

My objective is simple - I aim to access Level2 and insert a new Level3 object into it. Essentially, the desired code snippet appears as follows, yet due to the varying levels, I require a function capable of traversing through the object.

obj.Level1.Level2.Level3 = { 'status' : true}

Presented here is an excerpt of my code:

function updateStatusForLevel(nestedObj, categoryHierarchy){
        // The passed categoryHierarchy is ['Level1', 'Level2', 'Level3']; 
        var obj = nestedObj;

        angular.forEach(categoryHierarchy, function(value, key){
            obj = obj[value];


            if (key === categoryHierarchy.length - 1 && angular.isUndefined(obj)){
                 obj[value] = {}; // Here, I intend to include 'Level3' = {}
            }
        });
        obj.status = 'true'; // Finally, the status gets updated 
        console.info("The original obj is " + JSON.stringify(nestedObj));
    }

However, it seems like there might be a crucial element missing in my approach. Upon execution of the operation, the initial nestedObj remains unaltered (with only the obj being modified). I had initially anticipated this process to be relatively straightforward when navigating a deeply nested JSON structure. Why does the shallow copy fail to reflect the changes made to the original object?

Answer №1

Perhaps in this manner

function updateLevelStatus(data, hierarchy){
        // The hierarchy passed as an argument = ['Category1', 'Category2', 'Category3']; 
        if(hierarchy.length) {
             var shifted = hierarchy.shift();
             data[shifted] = {status: true};
             return updateLevelStatus(data[shifted], hierarchy);
       } else {
             return data;
       }
}

When calling

updateLevelStatus(data, ['category1', 'category2', 'category3'])
, the data object will be modified as shown below:

category1: Object
    category2: Object
        category3: Object
            status: true
        status: true
    status: true

Please note that this solution is simple; for a more comprehensive answer, consider using a tool like Plunker. In the meantime, you can test this in the browser dev console.

Answer №2

If you're looking to efficiently add a value from a specific path within nested objects, consider creating a versatile function that can handle this task instead of crafting individual ones. I've developed a factory called helper, serving as a repository for additional helper functions you might incorporate later on.

VIEW DEMO

JAVASCRIPT

  .factory('helper', function() {

    var helper = {};

    helper.set = function(object, path, value) {

      // preserve object reference
      var reference = object,
          // last key in the path
          lastKey;

      path = angular.isArray(path)? path: // convert to array if it's not an array
          angular.isString(path)? path.split('.'): // split into an array if it's a string
          false; // set to false and take no action if conditions above are not met

      // ensure path is valid
      if(path) {

        // get the last key from the path
        lastKey = path.pop();

        // iterate through references until all keys are processed
        reference = path.reduce(function(reference, key) {

          // check if current object reference is undefined
          if(angular.isUndefined(reference[key])) {
            // set current object reference as an object if it's undefined
            reference[key] = {};
          }

          // return current object reference for next iteration
          return reference[key];

        }, reference); 

        // assign value to last object reference
        reference[lastKey] = value;

      }

      return object;

    };

    return helper;

  })

  .run(function(helper) {

    var object1 = {},
        object2 = {},
        object3 = {},

        object4 = { 
          "level1" : { 
            "status" : true,
            "level2" : {}
          }
        };

    helper.set(object1, 'z.k.v.q', { status: false });
    // object1 = { z: { k: { v: { q: { status: false } } } } }
    console.log(object1);

    helper.set(object2, 'a.e.i.o.u', { status: true });
    // object2 = { a: { e: { i: { o: { u: { status: true } } } } } }
    console.log(object2);

    helper.set(object3, ['hello', 'world'], { status: undefined });
    // object3 = { hello: { world: { status: undefined } } }
    console.log(object3);

    helper.set(object4, 'level1.level2.level3', { status: true });
    // object4 = { status: true, level1: { level2: { level3: { status: true } } } }
    console.log(object4);

  });

Another option is to utilize lodash for enhanced object, array, and collection manipulation capabilities. The pertinent lodash function you'd need is _.set()

VIEW DEMO

JAVASCRIPT

  .service('_', function($window) {
    // add mixins here
    // explore lodash for customized data operations
    return $window._;
  })

  .run(function(_) {

    var object1 = {},
        object2 = {},
        object3 = {},

        object4 = { 
          "level1" : { 
            "status" : true,
            "level2" : {}
          }
        };

    _.set(object1, 'z.k.v.q', { status: false });
    // object1 = { z: { k: { v: { q: { status: false } } } }
    console.log(object1);

    _.set(object2, 'a.e.i.o.u', { status: true });
    // object2 = { a: { e: { i: { o: { u: { status: true } } } } }
    console.log(object2);

    _.set(object3, ['hello', 'world'], { status: undefined });
    // object3 = { hello: { world: { status: undefined } }
    console.log(object3);

    _.set(object4, 'level1.level2.level3', { status: true });
    // object4 = { status: true, level1: { level2: { level3: { status: true } }
    console.log(object4);

  });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most effective method for synchronizing data with HTML5 video playback?

I am currently developing a program that retrieves data from an android application and plays it back on a web browser. The android app allows users to record videos while logging data every 100ms, such as GPS location, speed, and accelerometer readings, i ...

Is utilizing React's useEffect hook along with creating your own asynchronous function to fetch data the best approach

After attempting to craft a function for retrieving data from the server, I successfully made it work. However, I am uncertain if this is the correct approach. I utilized a function component to fetch data, incorporating useState, useEffect, and Async/Awa ...

What could be causing my script files to not load when I use ajax load() to bring external content into a #content div?

I am currently troubleshooting why my JS files, or script files, are not loading when I bring external content into the #content DIV. While the HTML and CSS load correctly, the scripts do not. Upon page load, my index page, complete with head, body, sc ...

Strategies for bypassing Jquery form validation within a single form element

I want to implement form validation for all form elements, but I need to exempt one if a specific checkbox is checked. HTML <form id="reg_form"> <div class="control-group"> <div class="control"& ...

The issue lies in attempting to access allKeys on an NSDictionary that holds JSON

Trying to retrieve JSON data from a URL but encountering an error. Here is the code I am using: self.NsData=[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://doctorapp.5plus.co.il/categories.php"]]; id jsonCategories=[NSJSONSerialization JSONO ...

Error message "Uncaught in promise" is being triggered by the calendar function within the Ionic

Can someone assist me in creating a calendar feature for my app? My concept involves a button with text that, when clicked by the user, opens a calendar. However, I am encountering an error message: ERROR Error: Uncaught (in promise): TypeError: Cannot set ...

Sophisticated method for arranging three integers in javascript in descending order, followed by analyzing their relative distances

In developing an interactive infographic, I am working with three integers assigned to variables, each ranging from 0 to 50000. These numbers often have values that are close to each other, and I am looking for a way to identify when either 2, all 3, or no ...

Having trouble inserting a Button element into a li parent element

I'm attempting to insert a button inside an li element using the .appendChild method, but for some reason, it's not working. I also tried changing the parent's inner HTML. let inputElement = document.querySelector('#input'); let ...

Developing a Monitoring-Frontend Application with backbone.js

I am in the process of developing a tool for monitoring and analyzing statistics. The current setup is as follows: Collector-Backend: This component receives queries in JSON format from the frontend, fetches and stores them in a cache, and then notifies ...

Displaying numerous pointers on Google Maps by utilizing PHP arrays that are populated with information extracted from a MySQL database

I'm new to stack overflow and seeking some help. I have two PHP arrays storing latitude and longitude values based on user input. Using a basic Google Maps API tutorial map, how can I add multiple markers using only the latitude and longitude from th ...

Achieving success by correctly reaching the window's edge during an event (onscroll)

This happens to be my 1st inquiry. Specifically, I have a navigation menu with a transparent background and I am attempting to alter the background once it reaches the top edge of the window. window.addEventListener("scroll", navSticky); function navSt ...

How can I use JavaScript to retrieve information from a different webpage?

I am trying to extract data from another webpage using JavaScript, jQuery, or Ajax without using PHP. I came across a helpful example on Stack Overflow (link here). However, when I implement these codes in my index.html file, it doesn't seem to work. ...

Struggling with sending form data to the back end when uploading images in Angular

I've been facing a challenge trying to implement profile picture upload alongside standard text data and sending it all to the backend to create a new user through mongoose. Despite my efforts, using tools like ng-file-upload/angular-file-upload and e ...

The initial io.emit message seems to always be delayed or lost in transmission

io.on('connection',function(socket){ console.log('connected'); socket.on('disconnect',()=>{ console.log('a user disconnected'); }); socket.on('sendMessage',function(data){ const message = data.te ...

Exploring the capabilities of zooming on SVG elements using D3 within an Angular

I want to implement pan/zoom functionality on an SVG element. I came across a tutorial that suggested using d3.js for this purpose, you can find it here Below is the code I have tried: import { Component,AfterViewInit,OnInit } from '@angular/core&a ...

Discover the object in the initial array that is not included in the second array using AngularJS

Imagine having these two sets of objects: first set: [ { id: "123", title: "123", options: [] }, { id: "456", title: "456", options: [ { id: "0123", t ...

Share the hyperlink to a webpage with someone else

In my SQL command, I have a unique feature that retrieves the complete URL value of the current page: [##cms.request.rawurl##]. This code returns the entire URL. I need to send this address to another page and load it into a special div called "load-fac". ...

Unable to Locate Gulp Packages

Whenever I try to run the command gulp in my terminal, my gulp modules are not being found. Surprisingly, all other commands like node -v, gulp -v, and npm -v are working perfectly fine with the latest versions installed. I have tried running these command ...

Employ a adjusted column or partitioned table within the database

I need to store the following information in a MySQL database for notifications: id: VARCHAR(10) from_id: VARCHAR(10) to_id: VARCHAR(10) type: int(2) type_info: (The issue lies within this column) date : TIMESTAMP The type_info column's content is d ...

The issue of undefined database columns arises when attempting to transmit data from an HTML form to a MySQL database via Express

My primary objective is to develop a RestAPI using Node.js and test it in a small HTML application. With the guidance of my instructor, I successfully created the RestAPI based on an example and customized it to work with my own MySQL database. Testing ea ...