"Проблема в том, что req.body на стороне сервера помещает ответы на обе формы в массиве."
Это не совсем правильно,как это на самом деле клиент запрос, который на самом деле отправляется так.В основном это значение по умолчанию для x-www-form-urlencoded
данных, когда вы отправляете более одного значения для указанного имени поля и отправляет то, что интерпретируется как массивы для каждого поля вместо массив представлений так, как вы ожидаете.
Мне кажется, что вы могли бы отправлять данные в более подходящем формате (то есть предварительно составленном JSON-представлении объекта, который вы на самом деле представляете)хотите), но вместо фактического изменения кода, который отправляет форму, вы всегда можете просто преобразовать то, что отправлено, в разумное представление того, что вы хотите фактически вставить для нового Person
.
Предполагая, конечно,что единственные данные, присутствующие в req.body
, относятся к части experience
данных, которые будут добавлены, тогда простая инструкция преобразует это в массив записей, которые вы на самом деле хотите, а не просто все поля в виде массивов в том виде, в котором они есть на данный момент:
let data = req.body;
// For each total array length of a required field
let experience = [ ...Array(data.company.length)]
Get all the keys of the input object
.map((e,i) => Object.keys(data)
// Turn that into an object of singular values for the current index
.reduce((o,e) => ({ ...o, [e]: data[e][i] }),{})
)
ЕСЛИ у вас больше данных в req.body
и вы хотите только какЭто специфические поля, тогда это просто простая модификация с Array.filter()
.Запускается в браузере из этого поста на этот раз:
// Just simulating the content submitted in req.body
let req = {
body: {
"company" : [
"companyA",
"companyB"
],
"positionExperience" : [
"positionA",
"positionB"
],
"descriptionExperience" : [
"descriptionA",
"descriptionB"
]
}
};
// list of allowed fields
let whitelist = [
'company',
'positionExperience',
'descriptionExperience',
'websiteExperience',
'timeperiodExperience'
]
// Remove all but the wanted fields
let data = Object.entries(req.body)
.filter(([k,v]) => whitelist.indexOf(k) != -1)
.reduce((o,[k,v]) => ({ ...o, [k]: v }),{});
let experience = [ ...Array(data.company.length)]
.map((e,i) => Object.keys(data).reduce((o,e) => ({ ...o, [e]: data[e][i] }),{}))
console.log(experience)
Либо там, где это были единственные клавиши ввода req.body
, либо там, где вы извлекли только то, что хотели с помощью изменения выше, массив вывода experience
будет(как показано на примере данных, показанных в вопросе, который будет добавлен не так, как предполагалось):
[
{
"company" : "companyA",
"positionExperience" : "positionA",
"descriptionExperience" : "descriptionA"
},
{
"company" : "companyB",
"positionExperience" : "positionB",
"descriptionExperience" : "descriptionB"
}
]
Это означает, что experience
можно просто перенести в существующий код следующим образом:
const person = new Person({ file: req.file.path, experience });
Тогда, конечно, то, что будет сохранено, будет отражать ту же структуру:
{
"file": "whateverFileNameSupplied",
"experience": [
{
"company" : "companyA",
"positionExperience" : "positionA",
"descriptionExperience" : "descriptionA"
},
{
"company" : "companyB",
"positionExperience" : "positionB",
"descriptionExperience" : "descriptionB"
}
]
}
Лично я бы, вероятно, добавил бы smarts в интерфейс, чтобына самом деле представить данные в формате, который я действительно хочу.Но то, что у вас есть с массивами для каждого свойства, на самом деле типично для стандартного x-www-form-urlencoded
запроса POST, и если вы еще не хотите тратить время на отправку запроса JSON, который фактически соответствует тому, что вы хотите сохранить, тогдапреобразование, как описано выше, обычно является вашим кратчайшим путем к выполнению.