Oak / Deno, how to read multi part form, that has arrays

104 Views Asked by At

This doesn't work, for a form I have has strings, and arrays

In Deno / Oak, I can't get back the array of check boxes that are ticked (form encoding is multipart)

const body = await ctx.request.body({type: 'form-data'})
const formData: Record<string, string> = (await body.value.read()).fields

Output is this:

{
  fields: {
    title: "nn",
    author: "6516425a77906b55577811b0",
    summary: "nn",
    isbn: "nn",
    genre: "652077b1a36908a518ed91b4"
  }
}

Here, form encoding is urlencoded

const body = await ctx.request.body({type: 'form'}).value

Output is this (this seems more promising!),

URLSearchParams {
  [Symbol(list)]: [
    [ "title", "n" ],
    [ "author", "6516425a77906b55577811b0" ],
    [ "summary", "n" ],
    [ "isbn", "n" ],
    [ "genre", "6516425a77906b55577811aa" ],
    [ "genre", "6520455aaca724f1c8ac090b" ],
    [ "genre", "652077b1a36908a518ed91b4" ],
    [ "genre", "65207a7e57543b963db0f29f" ]
  ],
  [Symbol("url object")]: null,
  [Symbol("[[webidl.brand]]")]: Symbol("[[webidl.brand]]")
}

Using the same pug template, all I do in Node / Express is:

req.body

It works flawlessly, returning the check boxes ticked as an array.

Output is this (exactly what I need)!

{
  title: 'nn',
  author: '6516425a77906b55577811b0',
  summary: 'nn',
  isbn: 'nn',
  genre: [
    '6516425a77906b55577811aa',
    '6520455aaca724f1c8ac090b',
    '652077b1a36908a518ed91b4',
    '65207bb95ede58c78b1b68c7',
    '65215c985e4f1575c1aef29b'
  ]
}

I need the Oak output to look like this to work with it

Not sure, whether I should undo my last two weeks of Deno / Oak coding, back to Node, if such simple functionality cannot be achieved. Deno / Oak is meant to be newer and better right?

2

There are 2 best solutions below

0
Marcos Casagrande On

To access genre as an array from URLSearchParams, you have to use, URLSearchParams.getAll()

const genres = body.getAll('genre');
/*
["6516425a77906b55577811aa",
"6520455aaca724f1c8ac090b",
"652077b1a36908a518ed91b4",
"65207a7e57543b963db0f29f"]
*/
0
Sachin On

Thanks! I am aware of getAll. It's only that I need to get all the form data in one object in one call, like I can currently do in Express, as I don't always know how many fields there wil be in advance, or the names of the fields. It's also more flexible. If the data is in the express liek format (as a key value dictionary, where values can be an array), I can then pass the key / value object into a validation function that can then parse and trim all the data (detecting if the value of each key is an array, so it can handle those cases). Seems like I'd need to write a custom function to do this, as it's not really built into Oak.