Как преобразовать данные jQuery.serialize() в объект JSON?

Есть ли лучшее решение для преобразования данных формы, которые уже сериализованы функцией jQuery serialize(), когда форма содержит несколько полей ввода Array. Я хочу, чтобы иметь возможность преобразовывать данные формы в объект JSON для воссоздания некоторых других информационных таблиц. Так скажите мне лучший способ получить строку serialize, преобразованную как объект JSON.

<form id='sampleform'>
    <input name='MyName' type='text' /> // Raf

    <!--array input fields below-->
    <input name='friendname[]' type='text' /> // Bily
    <input name='fiendemail[]' type='text' /> // [email protected]

    <!--duplicated fields below to add more friends -->
    <input name='friendname[]' type='text' /> // Andy
    <input name='fiendemail[]' type='text' /> // [email protected]

    <input name='friendname[]' type='text' /> // Adam
    <input name='fiendemail[]' type='text' /> // [email protected]
</form>

Метод jquery, применяемый для получения данных

var MyForm = $("#sampleform").serialize();
/** result : MyName=Raf&friendname[]=Billy&fiendemail[][email protected]&friendname[]=Andy&fiendemail[][email protected]&friendname[]=Adam&fiendemail[][email protected]
*/

как мне сделать эти данные для объекта JSON? который должен иметь следующие данные JSON из приведенной выше формы.

{
    "MyName":"raf",
    "friendname":[
        {"0":"Bily"},
        {"1":"Andy"},
        {"2":"Adam"}
    ],
    "friendemail":[
        {"0":"[email protected]"},
        {"1":"[email protected]"},
        {"2":"[email protected]"}
    ]
}

Ответ 1

var formdata = $("#myform").serializeArray();
var data = {};
$(formdata ).each(function(index, obj){
    data[obj.name] = obj.value;
});

Простой и быстрый;)

Ответ 2

У меня недавно была эта точная проблема. Первоначально мы использовали метод jQuery serializeArray(), но это не включает элементы формы, которые отключены. Мы часто будем отключать элементы формы, которые "синхронизируются" с другими источниками на странице, но нам все равно нужно включать данные в наш сериализованный объект. Итак, serializeArray() отсутствует. Мы использовали селектор :input, чтобы получить все входные элементы (оба включены и отключены) в данном контейнере, а затем $.map() для создания нашего объекта.

var inputs = $("#container :input");
var obj = $.map(inputs, function(n, i)
{
    var o = {};
    o[n.name] = $(n).val();
    return o;
});
console.log(obj);

Обратите внимание, что для этого для каждого из ваших входов потребуется атрибут name, который будет именем свойства результирующего объекта.

На самом деле это немного изменилось из того, что мы использовали. Нам нужно было создать объект, который был структурирован как .NET IDictionary, поэтому мы использовали это: (я предоставляю его здесь, если это полезно)

var obj = $.map(inputs, function(n, i)
{
    return { Key: n.name, Value: $(n).val() };
});
console.log(obj);

Мне нравятся оба этих решения, потому что они - простое использование функции $.map(), и у вас есть полный контроль над вашим селектором (так, какие элементы вы в конечном итоге включаете в свой результирующий объект). Кроме того, дополнительный плагин не требуется. Обычный старый jQuery.

Ответ 3

Используйте плагин jQuery.serializeJSON. Он преобразует формы в том же формате, что и в объекте Rails params, который является очень стандартным и проверенным.

Ответ 4

Я использую этот очень маленький плагин jQuery, который я расширил с DocumentCloud:

https://github.com/documentcloud/documentcloud/blob/master/public/javascripts/lib/jquery_extensions.js

Это в основном две строки кода, но для этого требуется _.js(Underscore.js), поскольку она основана на функции reduce.

$.fn.extend({
  serializeJSON: function(exclude) {
    exclude || (exclude = []);
    return _.reduce(this.serializeArray(), function(hash, pair) {
      pair.value && !(pair.name in exclude) && (hash[pair.name] = pair.value);
      return hash;
    }, {});
  }
});

Расширения:

  • Он не сериализует входное значение, если оно null
  • Он может исключать некоторые входы путем передачи массива входных имен в аргумент exclude i.e. ["password_confirm"]

Ответ 5

Эквивалентное решение Данило Коллассо, с простыми и минусами sames .serializeArray() (в основном он использует .reduce вместо $.each).

С небольшими усилиями он позволяет реализовать дополнительные функции в ответах S.C., не требуя расширений.

$(selector).serializeArray()
    .reduce(function(accum, item) {
        // This 'if' allows ignoring some values
        if (-1 === [ 'ignoreThis', 'andThat' ].indexOf(item.name)) {
            // This allows ignoring NULL values
            if (item.value !== null) {
                accum[item.name] = item.value;
            }
        }
        return accum;
    },
    {
        // By supplying some initial values, we can add defaults
        // for, say, disabled form controls.
        preFilledName:  preFilledValue, // optional
        defaultName  :  defaultValue    // optional
    }
);

Ответ 6

Я думаю, что здесь есть много хорошего ответа, и я создал свою собственную функцию на основе этих ответов.

function formToJSON(f) {
    var fd = $(f).serializeArray();
    var d = {};
    $(fd).each(function() {
        if (d[this.name] !== undefined){
            if (!Array.isArray(d[this.name])) {
                d[this.name] = [d[this.name]];
            }
            d[this.name].push(this.value);
        }else{
            d[this.name] = this.value;
        }
    });
    return d;
}

//The way to use it :
$('#myForm').submit(function(){
    var datas = formToJSON(this);
    return false;
});

Хорошо, позвольте мне объяснить, почему я предпочитаю это решение... Если у вас есть входные данные с одним и тем же именем, все значения будут храниться в массиве, но если нет, значение будет храниться непосредственно как значение индекса в JSON... Здесь он отличается от Danilo Colasso answer, где возвращаемый JSON основан только на значениях массива...

Итак, если у вас есть форма с текстовым полем с именем content и multiples authors, эта функция вернется к вам:

{
    content : 'This is The Content',
    authors : 
        [
            0: 'me',
            1: 'you',
            2: 'him',
        ]
}

Ответ 7

Использование подчеркивания и jQuery

var formdata = $("#myform").serializeArray();
var data = {};
_.each(formdata, function(element){
// Return all of the values of the object properties.
  var value = _.values(element);
// name : value 
  data[value[0]] = value[1];
});
console.log(data); //Example => {name:"alex",lastname:"amador"}

Ответ 8

var formdata = $("#myform").serializeArray();

var data = {};

$(formdata ).each(function(index, obj){

         if(data[obj.name] === undefined)
              data[obj.name] = [];

          data[obj.name].push(obj.value);

});

Ответ 9

если вы используете ajax-запросы, то нет необходимости делать его json-object только $('#sampleform').serialize() работает превосходно или если у вас есть другая цель, вот мое решение:

var formserializeArray = $("#sampleform").serializeArray();   
var jsonObj = {};
jQuery.map(formserializeArray , function (n, i) {
    jsonObj[n.name] = n.value;
});

Ответ 10

При всех данных ответах возникла проблема, которая...

Если входное имя в виде массива, как name[key], но он будет генерировать так

 name:{
   key : value
 }

Например: если у меня есть такая форма.

    <form>
        <input name="name" value="value" >
        <input name="name1[key1]" value="value1" >
        <input name="name2[key2]" value="value2" >
        <input name="name3[key3]" value="value3" >
    </form>

Тогда он будет генерировать объект, как это со всем данным ответом.

Object {
    name : 'value',
    name1[key1] : 'value1',
    name2[key2] : 'value2',
    name3[key3] : 'value3', 
}

Но это должно генерироваться, как показано ниже, любой хочет получить как это, как показано ниже.

Object {
    name : 'value',
    name1 : {
        key1 : 'value1'
    },
    name2 : {
        key2 : 'value2'
    },
    name3 : {
        key2 : 'value2'
    }
}

Тогда попробуйте это ниже JS кода.

(function($){
    $.fn.getForm2obj = function(){
        var _ = {},_t=this;
        this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);}
        this.b = function(k,v,a = 0){ if(a) eval(k+".push("+v+");"); else eval(k+"="+v+";"); };
        $.map(this.serializeArray(),function(n){
            if(n.name.indexOf('[') > -1 ){
                var keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g),le = Object.keys(keys).length,tmp = '_';
                $.map(keys,function(key,i){
                    if(key == ''){
                        eval("ale = Object.keys("+tmp+").length;");
                        if(!ale) _t.b(tmp,'[]');
                        if(le == (i+1)) _t.b(tmp,"'"+n['value']+"'",1);
                        else _t.b(tmp += "["+ale+"]",'{}');
                    }else{
                        _t.c(tmp += "['"+key+"']",'{}');
                        if(le == (i+1)) _t.b(tmp,"'"+n['value']+"'");
                    }
                });
            }else _t.b("_['"+n['name']+"']","'"+n['value']+"'");
        });
        return _;
    }
})(jQuery);
console.log($('form').getForm2obj());
<!DOCTYPE html><html><head>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <title>Convert form data to JavaScript object with jQuery</title>
</head>
<body>
    <form>
        <input name="name" value="value" >
        <input name="name1[key1]" value="value1" >
        <input name="name2[key2]" value="value2" >
        <input name="name3[key3]" value="value3" >
        <input type="checkbox" name="name4[]" value="1" checked="checked">
        <input type="checkbox" name="name4[]" value="2">
        <input type="checkbox" name="name4[]" value="3">
    </form>
</body></html>

Ответ 11

если вы можете использовать ES6, вы могли бы сделать

const obj = arr.reduce((acc, {name, value}) => ({...acc, [name]: value}), {})

для сериализованного массива работает очень хорошо.