2

The Issue

I am trying to convert form inputs to a json object but having difficulty trying to achieve this, below is a snippet of the HTML which I have and the JSON which I'm trying to get.

{
    "2019-01-23": [
        {
            id: 1,
            period: 'am'
        },
        {
            id: 2,
            period: 'pm'
        }
    ]
}
<select name="dates[2019-01-23][0][id]">
    <option value="1" selected>1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="dates[2019-01-23][0][period]">
    <option selected>am</option>
    <option>pm</option>
</select>

<select name="dates[2019-01-23][1][id]">
    <option value="1">1</option>
    <option value="2" selected>2</option>
    <option value="3">3</option>
</select>
<select name="dates[2019-01-23][1][period]">
    <option>am</option>
    <option selected>pm</option>
</select>

What I've tried

var inputs = $(':input').serializeArray();
var json = [];
$.each(inputs, function(key, input) {
    var names = input.name.split(/\[(.*?)\]/);
    var data = [];

    data[names[1]] = [];
    data[names[1]][names[3]] = { id: null, period: null };
    if(names[5] == 'id') {
        data[names[1]][names[3]].id = input.value;
    }
    if(names[5] == 'period') {
        data[names[1]][names[3]].period = input.value;
    }

    json.push(data);
});

But this doesn't quite achieve what I'm after (multiple of the same date) and I'm getting a bit lost now, I'm sure there must be a way of doing this a lot easier.

1 Answer 1

1

First, match is more appropriate for your case than split.

Furthermore, since json is object literal, it should be initialised with empty object ({}), not array.

push is not quite appropriate for your case. It's better to use direct assignment instead.

So the code might look like this:

var inputs = $(':input').serializeArray();
var json = {};
$.each(inputs, function(key, input) {
    var keys = input.name.match(/([^\[\]]+)/g).slice(1);
    var date = keys[0], i = keys[1], id = keys[2];
    if (!json[date]) json[date] = [];
    if (!json[date][i]) json[date][i] = {};
    json[date][i][id] = input.value;
});
console.log(JSON.stringify(json));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<select name="dates[2019-01-23][0][id]">
    <option value="1" selected>1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
<select name="dates[2019-01-23][0][period]">
    <option selected>am</option>
    <option>pm</option>
</select>

<select name="dates[2019-01-23][1][id]">
    <option value="1">1</option>
    <option value="2" selected>2</option>
    <option value="3">3</option>
</select>
<select name="dates[2019-01-23][1][period]">
    <option>am</option>
    <option selected>pm</option>
</select>

Sign up to request clarification or add additional context in comments.

2 Comments

This almost works, however it's returning the date within the square brackets, e.g. [2019-01-23] instead of 2019-01-23. Any ideas?
@Karl Sorry, I forgot that match() with g flag returns full matches, not captured groups. Fixed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.