macek/jquery-serialize-object

Support ordered named keys

Closed this issue · 3 comments

Hashes/objects in JavaScript are not guaranteed to maintain their order when iterating them in JavaScript. Sometimes order is important.

How about an alternative serialization format where a form like

<input type="text" name="obj[b-key]" value="b-val">
<input type="text" name="obj[a-key]" value="a-val">

Will be serialized to:

{
    obj: [
        ["b-key","b-val"],
        ["a-key","a-val"]
    ]
}

instead of

{
   obj: {
       "b-key":"b-val", 
       "a-key": "a-val"
   }
}

Which might lose its order?

If you want to order your elements, you can use an array.

After a quick read of W3C HTML JSON form submission spec, you can see that others are of the same opinion.

If you'd like a serialized result as you've pasted above, you can achieve it with the following form

<input name="obj[0][]" value="b-key" type="hidden">
<input name="obj[0][]" value="b-val" type="text">
<input name="obj[1][]" value="a-key" type="hidden">
<input name="obj[1][]" value="a-val" type="text">

... though I can't see myself ever doing something like this. At any rate, it's possible.

If you want an key:value object, well "use an object," I'd say. If you want an ordered list, then an array fits the bill, yes?

@macek The problem I'm having is that when I initially render the form, they're ordered nicely like that. However, users can add new form sections right in the middle. I would have to renumber all subsequent form sections to maintain the order.

I didn't want to re-number everything, so I just used a random unique key, which is all I really care about -- as long as all objects that belong together have the same key, it will come through correctly on the backend. At least, when your backend is PHP where array key order is guaranteed.

This worked fine until I needed to process the form in JS. I figured the easiest to process the form was to just serialize it into an object so I could have easy access to all the data, which is when I found your project (thank you for writing this BTW).

I'm using underscore templates to render out the form sections. If I re-render all the form sections to increment the ID when a new sub-form is added, then I'd lose all the input data. So I can't do that. I'd have to work some jQuery and regex-fu to update the input names to increment the number for each of the subsequent ones, which doesn't sound fun either.

It's okay though, I decided it would be easiest to just iterate through the DOM in order, and pull out the data I need with a bunch of .val() calls.

macek commented

@mnpenner Upon revisiting this issue, I understand the situation you're in, but this is not a responsibility for this plugin — especially with the upcoming W3C HTML JSON form submission spec. This new spec clearly dictates how to structure the resulting JSON object.

I think this issue goes away with things like React.js, too. React allows you to re-render1 everything, so re-numbering your outputs as I described in my last comment would just part of a normal react loop. Coincidentally, if you were to use React, you probably wouldn't even need this plugin.

I suspect that bad templates systems like underscore et al will just wither away and die along with this plugin in the wake of much better tools like React.

Anyway, with the W3C and my personal objectives in mind, I'm going to close this issue as it's not really in the scope of this plugin. You're more than welcome to fork it and implement the change on your own, though I'm sure that's not the answer you wanted.

Best of luck.


1 React doesn't actually re-draw everything; it uses a clever diffing algorithim to generate a series of DOM changes.