How to Locate Values of JSON Array Objects by their Key Names

Is there a JavaScript implementation similar to HashMap for sorting JSON data in the following scenario?

Here is an example of the JSON structure:

{
"level1": {
    "level2": [{
        "product1": [
            "item1",
            "item2"
        ]
    }, {
        "product2": [
            "item1",
            "item2"
        ]
    }, {
        "product3": [
            "item5",
            "item6"
        ]
    }]
}
}

In my use case, when I have a key like 'product3', I need to retrieve its corresponding values such as "item5" and "item6". Although looping through the entire level2 object works, I am wondering if there is a more efficient way to directly find values using the key.

Answer №1

You have the option to construct either an object or a Map in ES2015:

Below is an ES5 example demonstrating the use of an object:

var map = Object.create(null);
data.level1.level2.forEach(function(entry) {
    Object.keys(entry).forEach(function(key) {
        map[key] = entry;
    });
});

Live demonstration:

var data = {
  "level1": {
    "level2": [{
      "product1": [
        "item1",
        "item2"
      ]
    }, {
      "product2": [
        "item1",
        "item2"
      ]
    }, {
      "product3": [
        "item5",
        "item6"
      ]
    }]
  }
};
var map = Object.create(null);
data.level1.level2.forEach(function(entry) {
  Object.keys(entry).forEach(function(key) {
    map[key] = entry;
  });
});
var name = "product2";
console.log(map[name]);

We initiate the object (map) using Object.create(null) to avoid inheriting properties like toString and valueOf.

The inner loop, following Object.keys, is required due to each object in the level2 array having a distinct property name. This structure may be unusual and somewhat cumbersome.

In ES2015 (also known as "ES6") with Map, the process is quite similar - simply utilize new Map and set:

var map = new Map();
data.level1.level2.forEach(function(entry) {
    Object.keys(entry).forEach(function(key) {
        map.set(key, entry);
    });
});

Live demonstration:

var data = {
  "level1": {
    "level2": [{
      "product1": [
        "item1",
        "item2"
      ]
    }, {
      "product2": [
        "item1",
        "item2"
      ]
    }, {
      "product3": [
        "item5",
        "item6"
      ]
    }]
  }
};
var map = new Map();
data.level1.level2.forEach(function(entry) {
    Object.keys(entry).forEach(function(key) {
        map.set(key, entry);
    });
});
var name = "product2";
console.log(map.get(name));

Answer №2

A concise solution using Array.some, Array.indexOf, and Object.keys functions to find a specific key within nested objects:

// Assuming 'json' is the initial object
var key = 'product3', values;
json['level1']['level2'].some((v) => Object.keys(v).indexOf(key) !== -1 && (values = v[key]), values);

console.log(values);  // Returns ["item5", "item6"]

Explanation:
arr.some(callback[, thisArg]) - This method checks if any element in an array satisfies a certain condition, here used to find the desired key value pair.
It iterates through the objects until it finds the specified key using

Object.keys(v).indexOf(key) !== -1
.
Once the key is found, its corresponding value is stored in the 'values' variable with && (values = v[key]).
This allows for efficient search without iterating through all objects unnecessarily.

Answer №3

If you want to restructure the data, one option is to transform it into a different format.

const data = {
"category1": {
    "subcategory1": [{
        "item1": [
            "detail1",
            "detail2"
        ]
    }, {
        "item2": [
            "detail3",
            "detail4"
        ]
    }]
}, 
  "category2": {
    "subcategory1": [{
        "item1": [
            "detail1b",
            "detail2"
        ]
    }, {
        "item2": [
            "detail3",
            "detail4"
        ]
    }]
  }
};

const transformedData = Object
  .keys(data)
  .reduce((obj, key) => {
    const value = data[key];
    
    return Object.assign(obj, {[key]:  transformSubcategory(value)});
  }, {});

console.log(transformedData.category1.subcategory1.item2);
console.log(transformedData.category1.subcategory1.item1);
console.log(transformedData.category2.subcategory1.item1);

function transformSubcategory(subcategory) {
  return Object
    .keys(subcategory)
    .reduce((obj, key) => {
      const value = subcategory[key];
    
      return Object.assign(obj, {[key]:  transformItem(value)});
    }, {});
}

function transformItem(item) {
  return item
    .reduce((obj, details) => {
      return Object.assign(obj, details);
    }, {});
}

Answer №4

For this demonstration (given that level1 and level2 are considered to be placeholders)

var obj = {
  "level1": {
    "level2": [{
      "product1": [
        "item1",
        "item2"
      ]
    }, {
      "product2": [
        "item1",
        "item2"
      ]
    }, {
      "product3": [
        "item5",
        "item6"
      ]
    }]
  }
};
var keyName = "product3";
var items = [];
Object.keys(obj).forEach(function(key) {
  Object.keys( obj[key] ).forEach(function(key1){               
      obj[key][key1].forEach(function(obj1){
         Object.keys(obj1).forEach(function(key2) {
            if (key2 == keyName) {
              items = items.concat(obj1[key2]);
            }
         });
      });
  });
});
console.log(items);

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

Tips for choosing at least three files in file upload control

How can I choose at least three files in a multiple file upload control? Should I integrate an AJAX FILE UPLOAD CONTROL TOOL KIT? I need to select a minimum of three files for the file upload control. If fewer than three files are selected, I want an ale ...

Pages devoid of content: Harnessing the power of Selenium automation with Chrome in

My goal is to automate a process using Python, Selenium, and the Chrome browser. Most pages are rendered correctly, however, there are some pages, such as chrome://version/, that the browser is unable to render. When I try general automation (without head ...

Attempting to retrieve JSON data from an API while currently working from local server

I need to retrieve JSON data from , but I keep encountering the error message: "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access." Here is the code I ...

Turn off Satellizer Popup Window Title Bar

Currently, I am implementing the satellizer plugin for Facebook authentication. However, I have encountered an issue with the default popup login window of Facebook, which includes a title bar and menu options. I would like to transform this popup into a m ...

Iterate through an array of objects and if a specific property matches a certain condition, extract that particular object - Using

I have an array of objects that I need to iterate through. If a match is found, I want to slice that object. var object = [ { "Name": 'Kshitij', "LastName": 'Rangari', "CountryBorn": 'India', ...

Steps for inserting a title to a marker on the google maps of android through google maps api after the marker has been successfully added

I have been working on an app that utilizes the Google Maps API in Android to display navigation paths between two points. The user can add markers by clicking on the map, with a marker appearing each time they click. Once two markers are added, the applic ...

Failed to read the JSON file

Upon accessing The browser displays the following content: [ {"title": "simple node (no explicit id, so a default key is generated)" }, {"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" }, {"key": "3", "title": "<span& ...

Monitor modifications to documents and their respective sub-collections in Firebase Cloud Functions

Is it possible to run a function when there is a change in either a document within the parent collection or a document within one of its subcollections? I have tried using the code provided in the Firebase documentation, but it only triggers when a docume ...

Utilizing the power of AWS Lambda in conjunction with moment JS to generate unique

My current time zone is GMT+8, and the AWS region I am using is Singapore (ap-southeast-1). I am facing an issue where there are discrepancies in date calculations between my local machine and when I deploy my code on AWS Lambda. My goal is to ensure that ...

Direct a flow to an unknown destination

What I am trying to achieve is writing a stream of data to nowhere without interrupting it. The following code snippet writes the data to a file, which maintains the connection while the stream is active. request .get(href) .on('response', func ...

Ensure your JavaScript files are securely wrapped to maintain functionality when they are concatenated

Currently, I am using PHP to combine several JS and CSS files. While the CSS concatenation works perfectly, some of the JS files break when combined. As a temporary solution, I stop them from being added together and they function normally as individual fi ...

Having trouble generating an image with JavaScript

I am currently working on incorporating an image onto a webpage using JavaScript. Surprisingly, even the alert('This function works!') is not displaying anything! What could be causing this issue? Please assist! <!DOCTYPE html> <html> ...

Utilizing Highcharts with NodeJS

Is anyone familiar with implementing Highcharts in Node.js? I am currently encountering a problem using [email protected]: var Highcharts = require('highcharts'), chart = Highcharts.chart(null, { series: [{ data: [1, 3, 2, 4 ...

Ensuring DIV Stays Within Window Limits using Javascript

Hi there! I'm working on a 'box' div that moves when you click arrows. How can I make sure the box stays within the window and doesn't go past the borders? Here's the fiddle: var elementStyle = document.getElementById("divId").st ...

A guide on selecting elements within an ng-repeat loop using Protractor

I've been trying to click on the checkbox under the repeat section, but my code isn't working as expected. Here's what I have: element.all(by.repeater('(spid in spids')).then(function(completeColumns) { completeColumns[1].click(); ...

Here's a method to verify a function prop was invoked using react-testing-library

There are 3 key files: First File: utilities.js export const utilities = () => ({ func: () => 'Function was executed', }); Second File: AppComponent.js import React from 'react'; import { utilities } from './utilities&apo ...

Pressing the button causes the text to transform temporarily before reverting back to its original state

One challenge I am facing is figuring out how to change the text of a button back to its original state after it has been clicked. For example, when a user clicks on a button that copies text to the clipboard, how can I make it so that the text changes tem ...

Unlocking the value of the "input" field within an EventListener function in Angular directly from the DOM

In my "characters" module, there is a form with a text field and a button. When the button is clicked, it triggers a function but I am struggling to retrieve the current input text and pass it to the async function. HTML: https://i.sstatic.net/DMF8w.png ...

foreverjs neglects to log the child process's console.log output to any log files

I currently have a nodejs server running that fetches data using the setInterval function every x seconds. Here is a snippet of that part of the app: startPolling () { debug('Snmp poller started'); timers.setInterval( this.poll( ...

Designing an accordion with the main content peeking out slightly before collapsing into place

Seeking assistance in creating an accordion that displays a snippet of content before collapsing. I'm facing difficulty starting this project. While a basic accordion is simple to implement, I am unsure how to show a portion of the content (such as t ...