Javascript将数组转换为对象数组
Posted
技术标签:
【中文标题】Javascript将数组转换为对象数组【英文标题】:Javascript Convert array to Array of Objects 【发布时间】:2021-01-07 17:04:51 【问题描述】:我有一个表单,我正在使用 Ajax 向 API 提交数据。该表单包含一个重复器,可帮助用户重复输入任意数量的数据。用户在几个步骤后提交表单。当我尝试将值绑定到 Object 时未绑定。 API 是使用 Spring Boot 构建的,默认情况下,Jackson 用于将 JSON 转换为 Objects。
这是完整的代码,
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)
);
)
在 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"
如果我将上述代码转换为以下格式,我希望它可以工作,因为我使用的是列表,杰克逊图书馆将能够识别这种格式
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"
]
我在javascript中尝试了很多方法来转换成这种格式,我们如何才能实现上述格式?
【问题讨论】:
您在这里尝试做什么有点不清楚。我不确定你的输入是什么,你的输出是什么。并且这两个样本都不是对象的合法 JS 表示(尽管后者如果包裹在
-
中。你想将什么转换成什么?你能告诉我们一些你尝试过的东西吗?
@ScottSauyet我修改了我的问题,不知道你能不能看懂,我真的不知道怎么问这个,是格式问题,你看到的就是我需要的格式第一个是我拥有的格式。如何将第一个 JSON 转换为最后一个 JSON 格式?
您如何获得该输入?它是如图所示的多行字符串吗?因为它仍然不是合法的 JS 格式。对象键可以包含任何字符,但在源代码或 JSON 中,不允许使用除字母数字字符 /$ /_ 之外的任何字符,除非包装在字符串中。也就是说,这是不合法的:act1[0].quantity: "4"
,但是这(将密钥包裹在字符串中)是合法的:"act1[0].quantity": "4"
。
【参考方案1】:
保留有用函数的个人库通常可以使这种转换更容易。我已经多次使用包含的assocPath
和hydrate
之类的函数,包括recent SO answer(其中包含有关它们的功能的更多详细信息。)
将我的解决方案放在一起涉及一些相当小的功能。我确实必须假设您的输入结构从问题中并不完全清楚,即显示的内容是真实 JS 格式的某种速记。如果没有,大部分代码可能仍然可以工作;只是可能需要一些额外的努力才能转换成可用的东西。
这就是它的样子:
// 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
使用我已经拥有的助手,为了构建它,我唯一需要的技巧就是编写一些代码来将这种样式输入:"act1[0].quantity"
转换为我更喜欢使用的样式,["act1", 0, "quantity"]
。该代码是makePath
,它取决于extractIndices
。虽然它们可以在这里轻松组合,但 extractIndices
看起来好像单独使用它可能有用。
使用它,我们可以将您上面的输入转换为:
[
[["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"]
]
然后在该结果上简单地调用hydrate
。
【讨论】:
你拯救了我的一天。非常感谢。 @SebrinThomas:我很高兴它有帮助,但我希望你带走的不仅仅是代码。更重要的是构建和重用许多简单函数以构建更复杂的函数的概念。以上是关于Javascript将数组转换为对象数组的主要内容,如果未能解决你的问题,请参考以下文章
我想用 JavaScript 将对象数组转换为对象 [重复]