1

I need to map an array of inputs to pass via an ajax call. Inputs look like this:

<input type="hidden" name="sizes[0][id]" value="0" class="sizes">
<input type="hidden" name="sizes[0][name]" value="Small" class="sizes">
<input type="hidden" name="sizes[1][id]" value="1" class="sizes">
<input type="hidden" name="sizes[1][name]" value="Medium" class="sizes">
<input type="hidden" name="sizes[2][id]" value="2" class="sizes">
<input type="hidden" name="sizes[2][name]" value="Large" class="sizes">

I'm trying to map it like the following, but it is not working as it doesn't grab the id or name field.

var sizes = $('input.sizes').map(function(){ return $(this).val(); }).get();

Maybe this needs to be recursive somehow?

Edit: The output needs to work with the following code:

$.ajax({
  type  : "POST",
  cache : false,
  data  : {
    sizes: sizes,
    ...
  },
  url   : 'http://what.does.the.fox/say',
  dataType : 'json',
  ...
});

Another update: This should create an array of objects that resemble the input name tag. ie:

var sizes = [
  { id: 0, name: 'Small' },
  { id: 1, name: 'Medium' },
  { id: 2, name: 'Large' }
];
6
  • Can you provide a representation of your desired serialization? What would the desired result look like as json? Commented Apr 30, 2014 at 19:54
  • Also I believe .map is already recursive Commented Apr 30, 2014 at 19:59
  • That still does not tell us what it needs to look like, it tells us that you want to send it over the to the server via ajax. What does sizes <- look like? Commented Apr 30, 2014 at 20:00
  • I don't see how there would be more than one way to setup the json like this. I guess like this: ['0': { id: 0, name: 'Small' },'1': { id: 1, name: 'Medium' },'2': { id: 2, name: 'Large' }] Commented Apr 30, 2014 at 20:04
  • But your inputs have no id attribute. EDIT: never mind, I see what you're after. Commented Apr 30, 2014 at 20:10

3 Answers 3

1

I found code online that is able to do this as I want it. This also makes it completely dynamic so it doesn't matter what fields are named, or how many there are. Here is the code I found here in a comment:

(function(jQuery){

 jQuery.fn.MytoJson = function(options) {

    options = jQuery.extend({}, options);

    var self = this,
        json = {},
        push_counters = {},
        patterns = {
            "validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
            "key":      /[a-zA-Z0-9_]+|(?=\[\])/g,
            "push":     /^$/,
            "fixed":    /^\d+$/,
            "named":    /^[a-zA-Z0-9_]+$/
        };


    this.build = function(base, key, value){
        base[key] = value;
        return base;
    };

    this.push_counter = function(key){
        if(push_counters[key] === undefined){
            push_counters[key] = 0;
        }
        return push_counters[key]++;
    };

    jQuery.each(jQuery(this).serializeArray(), function(){

        // skip invalid keys
        if(!patterns.validate.test(this.name)){
            return;
        }

        var k,
            keys = this.name.match(patterns.key),
            merge = this.value,
            reverse_key = this.name;

        while((k = keys.pop()) !== undefined){

            // adjust reverse_key
            reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');

            // push
            if(k.match(patterns.push)){
                merge = self.build([], self.push_counter(reverse_key), merge);
            }

            // fixed
            else if(k.match(patterns.fixed)){
                merge = self.build([], k, merge);
            }

            // named
            else if(k.match(patterns.named)){
                merge = self.build({}, k, merge);
            }
        }

        json = jQuery.extend(true, json, merge);
    });


    return json;
 }

})(jQuery);
Sign up to request clarification or add additional context in comments.

1 Comment

I'm glad you were able to find something and you're right - it is a fair amount of code to create the dynamic qualities that you want.
0

DEMO

var sizes = $('input.sizes').map(function(){ 
    return { id   : this.id,
             name : this.name,
             val  : $(this).val()
            }; 
}).get();

Note for jQuery-o-philes: in this case this.id is the same as $(this).attr('id'), its just that we don't need jQuery to get the id if we already have the element. Same thing with this.name.

2 Comments

I think you misunderstood what I was asking. I don't want the id and name fields from the input itself. Look at the name tag to see which value should be the id / name.
Thats insanely ugly. I'm going to change your html to do this, is that ok?
0

EDITED: This is what you want - http://jsfiddle.net/jayblanchard/2F5vD/3/ (Now new and improved with proper quotes!)

var dataString = '';
dataString += '[';
var inputLength = $('input.sizes').length;
$('input.sizes').each(function(index) {
    if( $(this).is('[name$="[id]"]') ) {
        dataString += '\'' + $(this).val() + '\':';
        dataString += '{ id:' + $(this).val() + ',';
    } else if( $(this).is('[name$="[name]"]') && 0 != inputLength -1 ) {
        dataString += ' name:\'' + $(this).val() + '\'},';
    } else {
        dataString += ' name:\'' + $(this).val() + '\'}';
    }
    inputLength--;
});
dataString += ']';

It produces the following output (that will now pass JSLint)-

[{"0":{ "id":"0", "name":"Small"},"1":{ "id":"1", "name":"Medium"},"2":{ "id":"2", "name":"Large"}}]

This pretty much used brute force methodology to get a JSON string and there may be some much easier ways to do this. this can easily be ported to a function that can be called over and over. I hope that it helps.

3 Comments

This is close, but instead of using "[" or "]" I want it to be an actual array. Same goes for "{" and "}" as objects. Also, I would prefer it were dynamic instead of reading specifically for id, and name, but that might be a lot more code.
Ah - that wasn't clear from your original post. As for being dynamic I'm not sure what you mean. You provided a distinct HTML set that you wanted converted. You specified an output in your comments. Can you be more specific?
Don't worry about it being dynamic.

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.