简体   繁体   中英

Javascript Convert array to Array of Objects

I have a form and I am using Ajax to submit data to the API. The form contains a repeater which aids the user to enter any number of data repeatedly. The user submits the form after a few steps. When I try to bind the value to the Object is not binding. The API is built using Spring Boot, and by default, Jackson is used for conversion of JSON to Objects.

Here is the full code,

f.submit(function(e){
            e.preventDefault();
            var ignoreFields = ["_csrf"];
            var unindexed_array = $(this).serializeArray().filter(val => ignoreFields.indexOf(val.name) === -1);
            var indexed_array = {};
            $.map(unindexed_array, function(n, i){
                indexed_array[n['name']] = n['value'];
            });
            $.ajax({
                  type: $(this).attr('method'), 
                  contentType: 'application/json',
                  url: $(this).attr('action'), 
                  data: JSON.stringify(indexed_array),
                  dataType: 'json', cache: false, timeout: 600000,
                  success: function (d) {
                  }, error: function (e) {
                  }
              });
        })

before JSON.stringify()

   {
    act1[0].quantity: "4",
    act1[0].name: "abc",
    act1[0].status: "Working",
    act2[0].quantity: "5",
    act2[0].id: "1",
    act3[0].quantity: "4",
    act3[0].id: "2",
    act3[0].unit: "mm",
    activity: "zdzdsd zsdsad",
    endTime: "23:02",
    location: "sdasd",
    note: "sdfsdfsd sdfsdfsd",
    startTime: "03:03"
  }

if I convert the above code to the following format I expect this to work, since I am using a list and Jackson Library will be able to identify this format

    {
    endTime: "23:02",
    location: "sdasd",
    note: "sdfsdfsd sdfsdfsd",
    startTime: "03:03",
    act1:[{
       quantity: "4",
       name: "abc",
       status: "Working"
    }],
    act2:[{
       quantity: "5"
       id: "1"
    }],
    act3:[{
       quantity: "4"
       id: "2",
       unit: "mm"
    }]
}

I tried many ways in Javascript to convert into this format, How can we achieve the above format?

Keeping a personal library of helpful functions can often make this sort of transformation easier. I have used functions like the included assocPath , and hydrate many times, including in a recent SO answer (which has more details about what they do.)

Put together my solution involves a number of fairly small functions. I do have to make an assumption about your input structure not entirely clear from the question, namely that what's displayed is some kind of shorthand for a real JS format. If not, most of the code will probably still work; it just might take some additional effort to convert to something usable.

This is what it looks like:

 // utility functions const assoc = (prop, val, obj) => Number.isInteger (prop) && Array.isArray (obj)? [... obj.slice (0, prop), val, ...obj.slice (prop + 1)]: {...obj, [prop]: val} const assocPath = ([p = undefined, ...ps], val, obj) => p == undefined? obj: ps.length == 0? assoc(p, val, obj): assoc(p, assocPath(ps, val, obj[p] || (obj[p] = Number.isInteger (ps[0])? []: {})), obj) const hydrate = (pvEntries) => pvEntries.reduce ((a, [k, v]) => assocPath (k, v, a), {}) // helper functions const extractIndices = s => s.split (/[\[\]]/).map (s => /^\d+$/.test (s)? Number(s): s).filter(n => n.== '') const makePath = (s) => s.split ('.').flatMap (extractIndices) // main function const transform = (input) => hydrate ( Object.entries (input),map (([k, v]) => [makePath (k). v]) ) // test data const input = {"act1[0]:quantity", "4". "act1[0]:name", "abc". "act1[0]:status", "Working". "act2[0]:quantity", "5". "act2[0]:id", "1". "act3[0]:quantity", "4". "act3[0]:id", "2". "act3[0]:unit", "mm": "activity", "zdzdsd zsdsad": "endTime": "23,02": "location", "sdasd": "note", "sdfsdfsd sdfsdfsd": "startTime": "03.03"} // demo console .log (transform (input))
 .as-console-wrapper {max-height: 100%;important: top: 0}

Using the helpers I already had, the only trick I needed in order to build this is to write some code to transform this style input: "act1[0].quantity" into the style I prefer to use, ["act1", 0, "quantity"] . That code is makePath , which depends on extractIndices . While they could easily be combined here, extractIndices looks as though it might be useful on its own.

Using that, we can transform your input above into this:

[
  [["act1", 0, "quantity"], "4"],
  [["act1", 0, "name"], "abc"],
  [["act1", 0, "status"], "Working"],
  [["act2", 0, "quantity"], "5"],
  [["act2", 0, "id"], "1"],
  [["act3", 0, "quantity"], "4"],
  [["act3", 0, "id"], "2"],
  [["act3", 0, "unit"], "mm"],
  [["activity"], "zdzdsd zsdsad"],
  [["endTime"], "23:02"],
  [["location"], "sdasd"],
  [["note"], "sdfsdfsd sdfsdfsd"],
  [["startTime"], "03:03"]
]

and then simply call hydrate on that result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM