Retrieve the value of a nested JSON object using the name of an HTML form field, without the use of eval

I am facing a similar issue to Convert an HTML form field to a JSON object with inner objects, but in the opposite direction.

Here is the JSON Object response received from the server:

{
    company : "ACME, INC.",
    contact : {
        firstname : "Daffy", 
        lastname : "Duck"
    }
}

Below is the structure of the HTML form:

<form id="myform">
    Company: <input type="text" name="company" />
    First Name: <input type="text" name="contact.firstname" />
    Last Name: <input type="text" name="contact.lastname" />
</form>

This is the (pseudo)code currently being used:

var formFields; 

for (var i = 0, iMax = formFields.length; i < iMax; i++) {

    var fieldName = formFields[i].getAttribute('name');
    eval("fieldValue = responseObject."+fieldName);

}

Although my solution works, I am seeking a method to eliminate using eval. Furthermore, the solution should be able to handle form fields with multiple dots in the field name.

Answer №1

Instead of:

eval("sFieldValue = oResponse."+sFieldName); 

For singular dotted fields, you can use:

sFieldValue = oResponse[sFieldName];

This method retrieves the value using its key.

If you require more complex actions, follow these steps:

  1. Split sFieldName at each occurrence of .
  2. Iterate over the array and navigate within oResponse until you find the desired value

A sample code implementation is as follows:

var node = oResponse, parts = sFieldName.split('.');
while(parts.length > 0) {
   node = node[parts.shift()];
}
// The variable 'node' now contains the desired value

For more insights on "Member Operators":
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators

Answer №2

To effectively handle a single property, you can use the following code snippet:

sFieldValue = oResponse[sFieldName]

However, when dealing with nested data like contact.firstname, you need to split the name by dots and iterate through each part using a loop:

var aFormFields; 

for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {

    var aFieldNameParts = aFormFields[i].getAttribute('name').split(".");
    var oFieldValue = oResponse;
    for(var j=0; j<aFieldNameParts.length; j++) {
        oFieldValue = oFieldValue[aFieldNameParts[j]];
    }
    var sFieldValue = oFieldValue;
}

Keep in mind that if a property doesn't exist, an error will be thrown. It's advisable to verify the existence of

oFieldValue[ aFieldNameParts[j] ]
before accessing it.

Answer №3

Instead of iterating over the input fields, a more efficient approach would be to loop through the JSON object directly:

function populateForm(form, jsonData, namespace) {
  namespace = namespace ? namespace + "." : "";
  for (var key in jsonData) {
    if (typeof jsonData[key] === "string") {
      var inputField = form.elements[namespace + key];
      if (inputField)
        inputField.value = jsonData[key];
    } else
      populateForm(form, jsonData[key], namespace + key);
  }
}

populateForm(document.getElementById("myform"), responseObject);

(not tested yet)

Answer №4

If your naming convention is consistent, you can transform the dot-notation into subscripts. Start by breaking down the field name with periods and then iterate or use recursion to convert each token into a subscript. Keep in mind that this method assumes that oResponse has a value for every field.

for (var i = 0; i < aFormFields.length; i++) {
    var sFieldName = aFormFields[i].getAttribute('name');
    var tokens = sFieldName.split('.');
    var cur = oResponse;

    for (var j = 0; j < tokens.length; j++) {
        cur = cur[tokens[j]];
    }

    sFieldValue = cur;
}

Answer №5

Consider this as a fusion of an answer and a question :)

At the moment, I am in the process of configuring my server to convert the data received from a form into JSON format, just like you...

In my scenario, the form will ultimately generate a JSON object with multiple subobjects that can have their own subobjects, leading to potential infinite recursion.

The current "solution" that I'm using feels somewhat off, but it does get the job done. The getRequestBody function takes input from req.body object in express.js, which essentially follows this structure:

{
  "ridic-ulously-deep-subobject": "value",
  "ridic-ulously-deep-subobject2": "value",
  "ridic-ulously-deep2-subobject3": "value"
}

The HTML code being utilized is:

<form>
    <input name="ridic-ulously-long-class-string" value="my value" />
  </form>

And here's the JavaScript function (designed to be generic - simply supply it with a req.body object like the one above and it should return a JSON object):

function getRequestBody(reqB){

  var reqBody = {};

  for(var keys in reqB) {

    var keyArr = keys.split('-');

    switch(keyArr.length){
      case 1:
        if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
        reqBody[keyArr[0]] = reqB[keys];
      break;

      case 2:
        if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
        if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};

        reqBody[keyArr[0]][keyArr[1]] = reqB[keys];
      break;

      case 3:
        if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
        if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};
        if(!reqBody[keyArr[0]][keyArr[1]][keyArr[2]]) reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = {};

        reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = reqB[keys];
      break;

      case 4:

      // ...
      //and so on, always one line longer
  }

    return reqBody;
}

Although this solution covers only 5 levels of subobjects currently, there may be instances where applications require reaching seven or even ten levels. It seems like a common predicament, yet my search yielded no results within a 10-minute span, hinting at possible missing keywords or absence of a suitable solution [as of now].

Is there someone out there with enough creativity and logic to streamline this complexity, or will I have to add further clutter to accommodate up to 10 sublevels?

I believe that the performance impact might not be significant in the end, but I genuinely prefer steering clear of creating such a monstrous function :D

Enjoy experimenting!

Jascha

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

How to make an Ajax "POST" request to the server using jQuery or AngularJS without sending any parameter data

"Execute a 'POST' request to the server by using the code provided below However, the parameter data is not being sent to the server. I have attempted both the jQuery Way and var request = $.ajax({ url: baseUrl, type:'post', da ...

"Preventing the propagation of a click event on an anchor tag with

Is there a way to prevent the parent anchor from executing its href when a child element is clicked, despite using stopPropagation? Here is the markup provided: <div id="parent"> <h5>Parent</h5> <a id="childAnchor" href="https:// ...

Transform the characters within a string into corresponding numerical values, calculate the total sum, and finally display both the sum and the original string

I'm looking to convert a string containing a name into numerical values for each character, ultimately finding the sum of all characters' numerical values. Currently, only the first character's value is being summed using .charAt(). To achie ...

Adjusting the size of images in a Bootstrap lightbox gallery

I am currently working on a website for an artist, making the galleries a key aspect. The website is built using Bootstrap, with the Lightbox for Bootstrap plugin being used for the galleries. Everything seems to be working well in terms of adjusting the i ...

Nested pages are causing jQuery plugins to malfunction

I am currently working on a website, but I am facing some issues with the product listing pages and the tips and tricks page. It appears that there is an issue with jMenu and jFlipBook plugins not functioning properly. Since I didn't develop the origi ...

I am curious if there is a wysiwyg web editor extension specifically designed for VS2010 available?

In my experience, I have been working with C#, HTML coding using VS2010 and MVC. Utilizing VS2010 has proven to be an invaluable tool for me in this process. Currently, I find myself needing to create some straightforward static web pages. I am wondering ...

How to Extract a URL from an Anchor Tag without an HREF Attribute Using Selenium

How can I make a link, which normally opens in a new window when clicked, open in the current window instead? The link does not have an href attribute, only an id and a class. For example: <a id="thisLink" class="linkOut">someLinkText</a> I r ...

What is the best way to sort through data if I enter more than three characters to filter the results?

Hey there, I'm currently in the process of developing a search bar that functions by displaying only filtered last names from a table when more than 3 characters are typed. The condition for filtering is empty. Here is the HTML code: <mat-form-fi ...

Tips for effectively passing navigation as props in React Navigation with Expo

How can I correctly pass navigation as props to another component according to the documentation? The navigation prop is automatically provided to each screen component in your app. Additionally, To type check our screens, we need to annotate the naviga ...

Sending an image file using AJAX and jQuery

I am currently using Mustache JS to generate a template called 'addUser1' for display purposes. However, when I execute this code, only the image location is being sent to the server, not the actual image itself. What could be causing this issue? ...

Creating Unique Names for DataMembers in WCF Generics

I currently have a WCF REST / JSON service that provides various types of data lists. I want to enhance each response by adding a revision number attribute. Let's take the example of a 'Car' class [DataContract] public class Car { [Dat ...

Some browsers are experiencing issues with Javascript functionality

My JavaScript code is functioning perfectly on my development machine in Chrome, Firefox, and Safari. However, when others test it on their browsers, the value update does not work at all. Can anyone suggest how I can replicate this issue locally? Browser ...

A method for performing precise division on numbers in JavaScript, allowing for a specific precision level (such as 28 decimal places)

I've searched extensively for a library that can handle division operations with more than 19 decimal places, but to no avail. Despite trying popular libraries like exact-math, decimal.js, and bignumber.js, I have not found a solution. How would you ...

Utilization of JSON and XML formats in web API for handling requests and responses

I'm in the process of building a WEBAPI using .NET, and I need to decide whether to accept requests in XML or JSON. I'm unsure which one is the best practice and what their advantages are. Any suggestions on this would be greatly appreciated. Tha ...

Unusual JavaScript Bug: Uncaught TypeError - Unable to access property 'url' of null

I encountered a peculiar JavaScript error. The following message appears in the console: Uncaught TypeError: Cannot read property 'url' of null (Line 83) The code on Line 83 looks like this: var image = '<img class="news_image_options ...

The challenge of maintaining coherence in AngularJS scopes

It's driving me crazy. Our integration with some ATSs involves sending queries and setting variables in the scope upon receiving responses. I always make sure to set the variables within a $scope.$apply() to ensure proper updating. Everything was work ...

How to implement setState within a Promise function using useEffect in React functional components with hooks?

I am struggling to set the value of a hook within a Promise function inside a useEffect(), and then store the returned promise value in the fruit hook so that it can be accessed in the return function of MyComponent() This is what I have attempted so far: ...

Error occurs while attempting to return a JSON record using an Ajax request

As I am still new to the concept of MVC and Ajax, please bear with me while I try to understand how they work together to fetch data from a database. I encountered the following error: parse error syntax error Unexpected token < [object, object] wh ...

Finding the measurement of a sofa using couch.get(data, headers, status)

After attempting to set up a node.js application with express.js by connecting to couchdb, I utilized the npm package called nodejs-couch. app.get('/', function(req, res) { couch .get(dbName, viewUrl) .then( function(data, heade ...

"Patience is key when it comes to waiting for an HTTP response

Looking for a solution in AngularJS, I have a service that calls the backend to get some data. Here is how the service looks: app.factory('myService', ['$http', '$window', '$rootScope', function ($http, $window, $ro ...