"Unleashing the Power of Effortless Object Unwr

Looking for a better way to convert a raw json snapshot from Firebase into a JS class. My current method is lengthy and inefficient. Does anyone have a more optimal solution?

Class:

class SuggestedLocation {
  country_slug
  region_slug
  slug
  marker_type
  typeInType
  geometry
  properties
  type
  id
  constructor(country_slug, region_slug, slug, marker_type, typeInType, geometry, properties, type, id) {
    this.country_slug = country_slug
    this.region_slug = region_slug
    this.slug = slug
    this.marker_type = marker_type
    this.typeInType = typeInType
    this.geometry = geometry
    this.properties = properties
    this.type = type
    this.id = id
  }
}

Current unwrapping technique:

static fromSnapshot(snapshot) {
let suggestedLocations = [new SuggestedLocation()]
if (snapshot.exists()) {
  const value = snapshot.val()
  // Monster loop with nested objects - currently inefficient
}
return new SuggestedLocationsObject(suggestedLocations)

}

Example Json:

{
  "united-kingdom" : {
    "calderdale" : {
      "rossendale-way" : {
        "accommodations" : {
          "Campground" : {
            "zO3HxZVELbd" : {
              "geometry" : {
                "coordinates" : [ -2.1901328761018704, 53.65022995288969 ],
                "type" : "Point"
              },
              "properties" : {
                "marker-color" : "#6e875f",
                "marker-size" : "medium",
                "marker-symbol" : "lodging",
                "name" : "",
                "place_id" : "zO3HxZVELbd",
                "plus_code" : ""
              },
              "type" : "Feature"
            }
          }
        }
      }
    }
  }
}

Answer №1

To analyze your snapshot data more efficiently, you can utilize the Object.entries method instead of just using Object.keys. This will allow you to retrieve both keys and values at once.

In addition, consider employing the map and flatMap functions to generate an array of instances of SuggestedLocation without explicitly using push.

If you find yourself bothered by multiple assignments to this.*, you might want to alter the constructor signature to accept an object as input rather than individual values. Then, use Object.assign for a streamlined transfer of values.

Regarding the initial element with undefined properties in the array of SuggestedLocation instances, its purpose may be related to scenarios where snapshot.exists() returns false. In such cases, this empty entry serves a specific function. However, it is unclear why this dummy entry is necessary when actual data is present.

Below is the code implementing the aforementioned concepts using plain JavaScript (non-TypeScript):

class SuggestedLocationsObject extends Array {
  constructor(arr) {
    super();
    Object.assign(this, arr);
  }
}

class SuggestedLocation {
  constructor(obj) {
    Object.assign(this, obj);
  }
}

function fromSnapshot(snapshot) {
    return new SuggestedLocationsObject(
      !snapshot.exists() 
      ? [new SuggestedLocation()] 
      : Object.entries(snapshot.val()).flatMap(([country_slug, regionSlugs]) =>
          Object.entries(regionSlugs).flatMap(([region_slug, slugs]) =>
            Object.entries(slugs).flatMap(([slug, markerTypes]) =>
              Object.entries(markerTypes).flatMap(([markerType, accomAmenityTypes]) =>
                Object.entries(accomAmenityTypes).flatMap(([accomAmenityType, typeInTypes]) =>
                  Object.entries(typeInTypes).flatMap(([typeInType, ids]) =>
                    Object.entries(ids).map(([id, {properties, geometry, type}]) =>
                      new SuggestedLocation({country_slug, region_slug, slug, markerType, typeInType, geometry, properties, type, id})
                    )
                  )
                )
              )
            )
          )
        )
    );
}

let data = {
  "united-kingdom" : {
    "calderdale" : {
      "rossendale-way" : {
        "accommodations" : {
          "Campground" : {
            "zO3HxZVELbd" : {
              "geometry" : {
                "coordinates" : [ -2.1901328761018704, 53.65022995288969 ],
                "type" : "Point"
              },
              "properties" : {
                "marker-color" : "#6e875f",
                "marker-size" : "medium",
                "marker-symbol" : "lodging",
                "name" : "",
                "place_id" : "zO3HxZVELbd",
                "plus_code" : ""
              },
              "type" : "Feature"
            }
          }
        }
      }
    }
  }
};

let snapshot = {
    exists() { return true },
    val() { return data }
}

let result = fromSnapshot(snapshot);

console.log(result);

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

Convert XML data into a structured table format

We have an XML file named "servers.xml" that needs to be parsed. This file is located on the same server where we want it to be parsed, in the same folder. <root> <list> <server> <server name="28 Disconnects La ...

There appears to be a JavaScript validation error occurring on the current page, however, you are able

For my datepicker, I want an error message to display if the user selects a date more than 5 years in the future, saying "You are ineligible for our program". The user should not be able to proceed to the next step unless this error message is ad ...

Failure to trigger the success action in ExtJS

I am currently utilizing struts2 for the server-side implementation combined with ExtJS4 for the user interface. I have a basic form that I submit to the server, but the response consistently goes to the failure case of the request even though I am just re ...

Easily retrieve JSON data from a specified URL or localhost website using Visual Studio Apache Cordova

I'm having trouble retrieving JSON data from both my URL and localhost website using Visual Studio Apache Cordova. When I try to debug it locally, the data displays correctly. However, once I release and install the app on my mobile phone, nothing app ...

Implementing custom CSS styles to a component in real-time with ng-style

When I use an angularjs component to create stylized pictures, the style is not applied correctly on the first visit to a page (refreshing the page shows the correct style). The CSS that should be applied is generated dynamically based on the height and wi ...

Having trouble with Material-UI Textfield losing focus after re-rendering? Need a solution?

I am currently utilizing Material-ui Textfield to display a repeatable array object: const [sections, setSections] = useState([ { Title: "Introduction", Text: "" }, { Title: "Relationship", ...

Setting compilerOptions.isCustomElement for VueJS 3 in a Laravel project: A step-by-step guide

I am currently working on integrating VueJS 3 into a Laravel project and utilizing a JS file to implement a markdown toolbar. The JS file contains functions that generate buttons for applying various markdown options. Everything is functioning properly, bu ...

"Implementing class names with hash function in Next.js version 14

What is the updated method to hash CSS class names for nextJS v14? The previous approach used to involve: const path = require("path"); const loaderUtils = require("loader-utils"); const hashOnlyIdent = (context, _, exportName) => ...

ng-options encounters duplicate data when using group by in Internet Explorer

The dropdown menu that lists states works fine in Google Chrome, but duplicates groups in Internet Explorer. In Chrome, there are 2 groups, but in IE there are 4. How can I fix this issue in IE as well? Thank you. Here is the code snippet: <!DOCTYPE h ...

Ways to display JSON data in Angular 2

My goal is to display a list of JSON data, but I keep encountering an error message ERROR TypeError: Cannot read property 'title' of undefined. Interestingly, the console log shows that the JSON data is being printed. mydata.service.ts import { ...

Delay the rendering of the MUI DataGrid column until after the DataGrid is visible on the screen

Would it be feasible to asynchronously load a column of data in the MUI DataGrid after the table is displayed on the screen? Retrieving this additional data from the database is time-consuming, so I aim to have it appear once the table has fully loaded. T ...

Creating a collapsible accordion feature with jQuery using a specific HTML layout: wanna learn how?

I am looking to create an accordion effect with the structure provided below. The goal is to have the corresponding article toggle when clicking on .booklist>li>a, allowing only one article to be open at a time. Can someone assist me with writing this scri ...

Guide on plotting latitude and longitude coordinates on Google Maps with Vue.js through JSON data fetched via AJAX

I have implemented a Vue.js script to fetch JSON data through an AJAX request. However, I am encountering issues with the code. <script> new Vue({ el: '#feed' , data: { details: [], }, mounted() { this.$nextTick(fu ...

What is the order of reflection in dynamic classes - are they added to the beginning or

Just a general question here: If dynamic classes are added to an element (e.g. through a jQuery-ui add-on), and the element already has classes, does the dynamically added class get appended or prepended to the list of classes? The reason for my question ...

Ways to organize backbone models, views, and collections using vim?

I am a fan of vim's folding feature, but I have encountered some challenges when trying to fold backbone models, views, and collections. This is because backbone does not follow the traditional prototype syntax, but instead uses a .extend() based synt ...

Having trouble with installing a React app using npx create-react-app my-app?

description needed for image Having trouble creating a react application using npx create-react-app my-app... Encountering errors shown in the image. Attempted npm init but it was unsuccessful. Included node.js and vs code in the path. ...

Error message: The function pokemon.map does not exist

I'm new to learning react and I've been working on creating a react app using the pokemon API. However, I've encountered an error that says TypeError: pokemon.map is not a function. I'm unsure why .map is not recognized as a function in ...

What is the best way to test chained function calls using sinon?

Here is the code I am currently testing: obj.getTimeSent().getTime(); In this snippet, obj.getTimeSent() returns a Date object, followed by calling the getTime() method on that Date. My attempt to stub this functionality looked like this: const timeStu ...

Is it possible to extract elements from a single list and insert them onto various pages?

Currently, I am retrieving items from a list using an ajax call. After constructing the HTML content, I insert these items onto a page. Now, I want to extract the same items and display them on another page with a different style. Is there a method to conn ...

The interval keeps resetting every time I want the initial one to expire first

I'm currently working on a battle system that utilizes intervals, and I've encountered an issue where it keeps refreshing instead of creating multiple intervals. When I stop pressing the button associated with it, everything goes back to normal. ...