marioizquierdo / jquery.serializeJSON

Serialize an HTML Form to a JavaScript Object, supporting nested attributes and arrays.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Serializing an Array of Objects

StephenEsser opened this issue · comments

I have an input field consisting of an array with nested values.

<input name="array[0][value]" type="text" value="Label 1">

I am currently using the following solution found on StackOverflow: http://stackoverflow.com/questions/1184624/convert-form-data-to-javascript-object-with-jquery/8407771#8407771

Which serializes this structure into:

array: [ { value: 'Label 1' } ]

However, when using this library it serializes down to:

array: { '0': { value: 'Label1' } }

Is there a way to do the same thing using marioizquierdo/jquery.serializeJSON?

I need to be able to serialize multiple levels of Arrays / Objects. A possible structure being:

array: [ { array: [ 'val' ], value: 'text' } ]

Let me know if this is possible, I've attempted to use useIntKeysAsArrayIndex but this doesn't seem to work with nested objects, only single level key / value.

Yes of course, just use the option useIntKeysAsArrayIndex: true, for example:

$('input').serializeJSON({useIntKeysAsArrayIndex: true});

Which instructs the serializer to assume numeric keys are array indexes.

Oh wait, I didn't see your last line. Seems like you already used the useIntKeysAsArrayIndex option and didn't work. Can you be more specific about what is not working? Please show the HTML and the serialization that didn't work as expected.

Your example:

<input name="array[0][value]" type="text" value="Label 1">

Should serialize like this:

$('input').serializeJSON({useIntKeysAsArrayIndex: true});
// =>
{"array": [{"value": "Label 1"}]}

Thank you for such a fast reply, that's awesome. I've simplified the code down to a single input. This is what I have.

<form id="form-id">
  <input name="array[0][value]" value="value">
</form>

My testing function which I override submit: ( I am serializing the form, do I need to serialize inputs individually?)

  function testFormSubmit(event) {
    event.preventDefault();
    
    $.ajax({
        url: '/route/id/other_route/secret_id',
        type: 'PUT',
        data: $('#form-id').serializeJSON({ useIntKeysAsArrayIndex: true })
      })
      .done(function() {
        // Super Top Secret Code
      });
  }

And this is what I get on the server:

{"array"=>{"0"=>{"value"=>"value"}}}

Disclaimer: I didn't install this with NPM, I tested by copying the javascript directly into my project. I tried both the minified and un-minified versions. I don't know if this would cause problems.

(I'm fighting with webpack currently, will update to NPM when I have this figured out)

I don't know if this is anymore helpful, but the following HTML serializes into an Array as expected when using useIntKeysAsArrayIndex. I removed the nested value object.

<form id="form-id">
  <input name="array[0]" value="value">
</form>

Returns to the server:

{"array"=>["value"]}

Toggling the useIntKeysAsArrayIndex between false and true with this data structure works as I would expect. But <input name="array[0][value]" value="value"> does not

Yup, based on the way you describe it, there's a bug.

On this HTML:

<form id="form-id">
  <input name="array[0][value]" value="value">
</form>

The following serialization:

$('#form-id').serializeJSON({useIntKeysAsArrayIndex: true});

Should return this:

{"array": [{"value": "value"}]}

But it seems like it's returning this instead (bug!):

{"array"=>{"0"=>{"value"=>"value"}}}

Which is the same as if the useIntKeysAsArrayIndex were disabled. This gives a hint, the error may be that it is not being reclusively applied or something like that. I'll get to it ASAP. Thanks for reporting!

I added a test with exactly this input and everything seems to be working as expected: 7fc7e9b

This means that the bug is not in serializeJSON, but somewhere in you code. I would double check that you don't have a spelling error (although serializeJSON would know about invalid options).

Maybe the issue is in the way you send the ajax request? The jQuery.axaj data parameter is supposed to be a plain object, that will get serialized as "application/x-www-form-urlencoded" by default. That may be doing the undesired transformations. Why don't you try this instead?

  function testFormSubmit(event) {
    event.preventDefault();
    var obj = $('#form-id').serializeJSON({ useIntKeysAsArrayIndex: true });
    // console.log(">>> serialized obj: ", obj); // uncomment this to double check!
    var jsonString = JSON.stringify(obj);
    // console.log(">>> serialized json: ", jsonString); // uncomment this to double check!
    
    $.ajax({
        url: '/route/id/other_route/secret_id',
        method: 'PUT',
        contentType: "application/json; charset=utf-8", // <<== IMPORTANT!!
        data: jsonString
      })
      .done(function() {
        // Super Top Secret Code
      });
  }

I hope this helps your case. I will close this issue as it seems everything is fine with serializeJSON. Good luck!

Thanks for the help! Your suggestion above works as I would expect.

The real mystery now is why the other serialization library works and this one doesn't when passed directly into the ajax data parameter. I'll continue forward with your example.

Thanks again!