Navigating to lower levels of JSON data in JavaScript instead of starting with the top level

Using a microservice, I fetch multiple sets of JSON data and display them on a Vue.js-powered page. The structure of the data is as follows:

{"data":{"getcompanies":
  [
   {"id":6,"name":"Arena","address":"12 Baker Street","zip":"15090"}, 
   {"id":7,"name":"McMillan","address":null,"zip":"15090"},
   {"id":8,"name":"Ball","address":"342 Farm Road","zip":"15090"}
  ]
 }}

{"data":{"getusers":
  [{"id":22,"name":"Fred","address":"Parmesean Street","zip":"15090"}, 
   {"id":24,"name":"George","address":"Loopy Lane","zip":"15090"},
   {"id":25,"name":"Lucy","address":"Farm Road","zip":"15090"}]}}

{"data":{"getdevices":
  [{"id":2,"name":"device type 1"}, 
   {"id":4,"name":"device type 2"},
   {"id":5,"name":"device type 3"}]}}

I have successfully extracted this data individually using code like this:

getCompanies() {
  this.sendMicroServiceRequest({
    method: 'GET',
    url: `api/authenticated/function/getcompanies`
  })
  .then((response) => {
    if(response.data) {
      this.dataCompanies = response.data.getcompanies    
    } else {
      console.error(response)
    }
  }).catch(console.error)
}

The methods getUsers() and getDevices() function in a similar manner. The output of getCompanies() is:

[{"id":6,"name":"Arena","address":"12 Baker Street","zip":"15090"}, 
 {"id":7,"name":"McMillan","address":null,"zip":"15090"},
 {"id":8,"name":"Ball","address":"342 Farm Road","zip":"15090"}]

This data is then displayed in a table on the Vue template without any issues.

However, managing additional microservices calls could become cumbersome in the future.

I am seeking a more efficient way to bypass the response.data.*whatever* and directly access those id records with a reusable call. Unfortunately, I am facing challenges in achieving this. I have tried various approaches but haven't been successful in accessing the required data chunk smoothly.

Even though my latest attempt does yield results, it presents individual array elements which I would prefer to avoid manipulating into a JSON structure.

If you have any suggestions, hints, or guidance on how to streamline this process, please share your insights. They will be greatly appreciated!

Answer №1

In my opinion, it's more beneficial to explicitly state how you are accessing the object. It appears that the object key aligns with the name of the microservice function. If this is the case:

getData(functionName) {
    return this.sendMicroServiceRequest({
        method: 'GET',
        url: "api/authenticated/function/" + functionName
    })
    .then( response => response.data[functionName] )
}
getCompanies(){
    this.getData("getcompanies").then(companies => {
        this.dataCompanies = companies
    })
}

Answer №2

let arr = {info: ['y']};
let obj = {info: {getdata: 'y'}};

console.log(arr.info[0]);
console.log(Object.values(obj.info)[0]);

arr.data[0] is suitable if data was an array. If you want the first element of an object, use Object.values(response.info)[0] instead. The method Object.values changes an object to an array of its values.

The methods Object.keys and Object.entries also provide arrays of keys and key-value pairs respectively.

Note that objects do not guarantee order, so this only works in your scenario because info has only one key and value pair. In other cases, you may need to iterate through the entries to find the specific entry you seek.

Answer №3

startValue

We will kick things off with a basic function called startValue. This function retrieves the first value from an object, or throws an error if no value is found -

const x = { something: "foo" }
const y = {}

const startValue = t =>
{ const v = Object.values(t)
  if (v.length)
    return v[0]
  else
    throw Error("empty data")
}

console.log(startValue(x)) // "foo"
console.log(startValue(y)) // Error: empty data

fetchData

Next up, we create a generic function called fetchData. We utilize our startValue function within this chain without including any console.log or .catch; that decision is left to the caller -

fetchData(url) {
  return this
    .sendMicroServiceRequest({ method: "GET", url })
    .then(response => {
      if (response.data)
        return response.data
      else
        return Promise.reject(response)
    })
    .then(startValue)
}

Subsequently, we define fetchCompanies, fetchUsers, and so on -

fetchCompanies() {
  return fetchData("api/authenticated/function/getcompanies")
}

fetchUsers() {
  return fetchData("api/authenticated/function/getusers")
}

//...

async and await

To enhance the fetchData function, consider implementing async and await -

async fetchData(url) {
  const response =
    await this.sendMicroServiceRequest({ method: "GET", url })
  return response.data
    ? startValue(response.data)
    : Promise.reject(response)
}

demonstrating the power of generics

It could be argued that the need for the fetch* functions has diminished -

async getAll() {
  return {
    companies:
      await fetchData("api/authenticated/function/getcompanies"),
    users:
      await fetchData("api/authenticated/function/getusers"),
    devices:
      await fetchData("api/authenticated/function/getdevices"),
    // ...
  }
}

In the example above, three requests using await fetchData(...) are made sequentially. If you prefer parallel execution, the following demonstrates how to achieve that -

async getAll() {
  const requests = [
    fetchData("api/authenticated/function/getcompanies"),
    fetchData("api/authenticated/function/getusers"),
    fetchData("api/authenticated/function/getdevices")
  ]
  const [companies, users, devices] = Promise.all(requests)
  return { companies, users, devices }
}

handling errors

Lastly, error handling should be left to the caller and not incorporated into our generic functions -

this.getAll()
  .then(data => this.render(data)) // some Vue template
  .catch(console.error)

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

Invoking a Method in a React Component from its Parent Component

I am new to React and I have a question regarding how to call a method from a child component within the parent component. For example: var ChildClass = class Child { howDoICallThis () { console.log('Called!') } render () { retur ...

The jQuery slider's next button is not functioning as intended

jQuery('#slider-container').bjqs({ 'animation' : 'slide', 'width' : 1060, 'height' : 500, 'showControls' : false, 'centerMarkers' : false, animationDuration: 500, rotationS ...

Is there a way to stop a music track from playing?

function playMusic(){ var music = new Audio('musicfile.mp3'); if (music.paused) { music.play(); } else { music.pause(); } } <input type="button" value="sound" onclick="playMusic()" ...

Using AJAX/JQuery along with PHP to instantly send notifications without refreshing the page for a contact form

Website URL: This website was created by following two separate tutorials, one for PHP and the other for AJAX. The main objective was to develop a contact form that validates input fields for errors. If no errors are found, a success message is displayed ...

Creating dynamic images in Node.js using JavaScript without relying on HTML5 canvas

Hello everyone, I'm excited to be posting my first question on stackoverflow! Hey there, it's wabsol. I've been diving into the world of nodejs and loving every minute of it. I'm interested in creating a window and/or drawing an image ...

Struggling with getting the JavaScript, scss, and CSS television animation to turn on and off properly? Seeking assistance to troubleshoot this

After finding this javascript code on Codepen and seeing that it worked perfectly in the console there, I tried to run it on my computer with jQuery but it didn't work outside of Codepen. Even when attempting to use it on JSfiddle or compile the SCSS ...

Is there a method to obtain specific props for focused tabBar badges to customize the background color accordingly?

Is there a way to specify focused props in tabBarBadgeStyle to customize the background color? options={{ tabBarLabel: "Teams", tabBarBadge: '3', tabBarBadgeStyle: { backgroundColor: ORANGE ...

How can you access the URL of a resource action in Angular?

In my Angular application, I have created a resource named 'Files' with the following definition: app.factory('Files', function($resource) { return $resource('/api/accounts/:account_id/sites/:site_id/files/:file_id'); }); ...

Is it possible to pass a random variable into an included template in Jade?

In my jade template called 'main page', I have a reusable template named 'product template'. The 'product template' is designed to display dynamic data and needs to be flexible enough to be used in multiple pages without being ...

Step-by-step guide on generating a JSON object list in Python 2.7

Currently, I am in the process of converting an XML file to a JSON file. To accomplish this task, I begin by opening the XML file, utilizing the xmltodict module, and then employing the .get method to navigate the tree structure up to the desired level. Th ...

An alternative to PHP's exec function in Node.js

I am interested in developing a piece of software using C (such as prime number factorization) and hosting it on my web server with Node.js. Following that, I would like to create an HTML document containing a form and a button. Upon clicking the button, ...

Submitting a Yii 2 form automatically when it loads

Pjax::begin(); $form = ActiveForm::begin(); echo $form->field($model, 'testdata', [ 'inputOptions' => [ 'class' => 'form-control input-xsmall input-inline' ], ...

Tips for overriding ng-disable in AngularJSUnleashing the

This is a comment box using AngularJS: <tr> <td colspan="5"><br/>Comments* <div><textarea class="form-control" rows="3" cols="60" ng-model="final_data.drc_scope" placeholder="Add comments here" ng-disabled="is_team==0 || isDis ...

Is there a way to reverse the upside-down text generated by OffscreenCanvas.getContext().fillText()?

When using OffscreenCanvas.getContext().fillText() to generate text and then OffscreenCanvas.transferToImageBitmap() to create a map, I noticed that the text appeared flipped upside down when applied as a texture in a threejs project. The image clearly sho ...

I am looking to adjust the height of my MUI Grid component

Recently exploring React, and I'm looking to set a height limit for MUI Grid. I've structured my project into 3 sections using MUI grid components. My goal is to restrict the page height in order to eliminate the browser scrollbar. If the conten ...

What is the best way to create a text input that is both secure and non-editable?

While I am aware of the <input type="text" readonly /> possibility, it is not entirely secure. For example, if there is an input field that must remain uneditable by users, making it "readonly" can still be bypassed by inspecting the code and remov ...

Failed to retrieve the JSON data table

I'm having trouble accessing and downloading data from the following link: My setup is on a Linux Ubuntu server with no display, GUI or local access - only remote SSH connection available. I've attempted various command line tools (including Pha ...

Connecting a Vue js model data to a Select2 select box

Utilizing select2 to improve an html select element, I am facing challenges in binding the value of the select element to a Vue variable because Select2 appears to be causing interference. Is there an optimal approach to achieve this data binding and even ...

Can React-Select be utilized in the browser directly from the CDN?

Is it possible to utilize react-select directly in the browser without using bundlers nowadays? The most recent version that I could find which supports this is 2.1.2: How to import from React-Select CDN with React and Babel? In the past, they provided r ...

What is the best way to retrieve the name of an element or component using JavaScript

I'm currently working on a webpage that includes ASP.NET panels and JavaScript which retrieves all components present on the page: var items = Sys.Application.getComponents(); My goal is to obtain the name/ID of each element stored in the 'item ...