jquery - values - js serialize array




Konvertieren von Formulardaten in JavaScript-Objekte mit jQuery (20)

Wie konvertiere ich alle Elemente meines Formulars in ein JavaScript-Objekt?

Ich möchte eine Möglichkeit haben, automatisch ein JavaScript-Objekt aus meinem Formular zu erstellen, ohne jedes Element durchlaufen zu müssen. Ich will keine Zeichenkette, wie von $('#formid').serialize(); Ich möchte auch nicht, dass die Map von $('#formid').serializeArray();


Width all Given Antwort dort ein Problem, das ist ...

Wenn der Name der Eingabe array wie name[key] , wird dies jedoch wie folgt generiert

 name:{
   key : value
 }

Zum Beispiel: Wenn ich ein Formular wie dieses habe.

    <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>

Dann wird es Objekt mit allen gegebenen Antworten erzeugen.

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

Aber es muss wie unten generiert werden, jeder möchte so wie unten kommen.

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

Dann probiere dies unter js code.

(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);
$('form').getForm2obj();

Konvertieren von Formularen in JSON WIE EIN CHEF

Aktuelle Quelle ist GitHub und Laube.

$ bower installiere jquery-serialize-object

Der folgende Code ist jetzt veraltet .

Der folgende Code kann mit allen Arten von Eingabe-Namen arbeiten; und behandeln sie genau so, wie Sie es erwarten.

Beispielsweise:

<!-- all of these will work! -->
<input name="honey[badger]" value="a">
<input name="wombat[]" value="b">
<input name="hello[panda][]" value="c">
<input name="animals[0][name]" value="d">
<input name="animals[0][breed]" value="e">
<input name="crazy[1][][wonky]" value="f">
<input name="dream[as][vividly][as][you][can]" value="g">
// output
{
  "honey":{
    "badger":"a"
  },
  "wombat":["b"],
  "hello":{
    "panda":["c"]
  },
  "animals":[
    {
      "name":"d",
      "breed":"e"
    }
  ],
  "crazy":[
    null,
    [
      {"wonky":"f"}
    ]
  ],
  "dream":{
    "as":{
      "vividly":{
        "as":{
          "you":{
            "can":"g"
          }
        }
      }
    }
  }
}

Verwendung

$('#my-form').serializeObject();

Die Zauberei (JavaScript)

(function($){
    $.fn.serializeObject = function(){

        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]++;
        };

        $.each($(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 = $.extend(true, json, merge);
        });

        return json;
    };
})(jQuery);

Benutzen:

function form_to_json (selector) {
  var ary = $(selector).serializeArray();
  var obj = {};
  for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value;
  return obj;
}

Ausgabe:

{"myfield": "myfield value", "passwordfield": "mypasswordvalue"}

Die einfachste und genaueste Methode, die ich für dieses Problem gefunden habe, war die Verwendung von BBQ-Plugin oder dieses (die etwa 0,5 KB Größe ist).

Es funktioniert auch mit multidimensionalen Arrays.

$.fn.serializeObject = function()
{
	return $.deparam(this.serialize());
};


Du kannst das:

var frm = $(document.myform);
var data = JSON.stringify(frm.serializeArray());

Siehe JSON .


Ein-Liner (keine anderen Abhängigkeiten als jQuery), verwendet die Bindung fester Objekte für die Funktion Pass-zu- map Methode.

$('form').serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]

Was es macht?

"id=2&value=1&comment=ok" => Object { id: "2", value: "1", comment: "ok" }

geeignet für progressive Web-Apps (sowohl reguläre Formular-Übermittlungsaktionen als auch Ajax-Anfragen können problemlos unterstützt werden)


Einfachheit ist hier am besten. Ich habe eine einfache Zeichenfolge mit einem regulären Ausdruck ersetzt, und sie funktionierten wie ein Zauber bis jetzt. Ich bin kein Experte für reguläre Ausdrücke, aber ich wette, Sie können sogar sehr komplexe Objekte bevölkern.

var values = $(this).serialize(),
attributes = {};

values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) {
    attributes[name] = value;
});


Ich bevorzuge diesen Ansatz, weil: Sie müssen nicht über 2 Sammlungen iterieren, Sie können andere Dinge als "Name" und "Wert" bekommen, wenn Sie müssen, und Sie können Ihre Werte bereinigen, bevor Sie sie im Objekt speichern ( wenn Sie Standardwerte haben, die Sie nicht speichern möchten, zum Beispiel).

$.formObject = function($o) {
    var o = {},
        real_value = function($field) {
            var val = $field.val() || "";

            // additional cleaning here, if needed

            return val;
        };

    if (typeof o != "object") {
        $o = $(o);
    }

    $(":input[name]", $o).each(function(i, field) {
        var $field = $(field),
            name = $field.attr("name"),
            value = real_value($field);

        if (o[name]) {
            if (!$.isArray(o[name])) {
                o[name] = [o[name]];
            }

            o[name].push(value);
        }

        else {
            o[name] = value;
        }
    });

    return o;
}

Verwenden Sie so:

var obj = $.formObject($("#someForm"));

Nur in Firefox getestet.


Ich habe ein Problem mit Tobias Cohens Code (ich habe nicht genug Punkte, um es direkt zu kommentieren) gefunden, was ansonsten für mich funktioniert. Wenn Sie zwei Auswahloptionen mit demselben Namen haben, beide mit Wert = "", erzeugt der ursprüngliche Code "name": "" anstelle von "name": ["", ""]

Ich denke, das kann durch Hinzufügen von "|| o [this.name] == ''" zur ersten if-Bedingung behoben werden:

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] || o[this.name] == '') {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

Ich hatte das gleiche Problem in letzter Zeit und kam mit diesem .toJSON jQuery Plugin heraus , das ein Formular in ein JSON Objekt mit der gleichen Struktur umwandelt. Dies ist auch besonders nützlich für dynamisch generierte Formulare, bei denen der Benutzer mehr Felder an bestimmten Stellen hinzufügen soll.

Der Punkt ist, dass Sie tatsächlich ein Formular erstellen möchten, so dass es eine Struktur selbst hat. Sagen wir, Sie möchten ein Formular erstellen, in das der Benutzer seine Lieblingsorte in der Stadt einfügt: Sie können sich dieses Formular als <places>...</places> vorstellen <places>...</places> XML-Element, das eine Liste von Orten enthält, die der Benutzer mag, also eine Liste von <place>...</place> -Elementen, von denen jedes zum Beispiel ein <name>...</name> -Element enthält, a <type>...</type> und dann eine Liste von <activity>...</activity> -Elementen, um die Aktivitäten darzustellen, die Sie an einem solchen Ort ausführen können. Ihre XML-Struktur würde also so aussehen:

<places>

    <place>

        <name>Home</name>
        <type>dwelling</type>

        <activity>sleep</activity>
        <activity>eat</activity>
        <activity>watch TV</activity>

    </place>

    <place>...</place>

    <place>...</place>

</places>

Wie cool wäre es, ein JSON-Objekt zu haben, das genau diese Struktur repräsentiert, so dass Sie entweder:

  • Store this object as it is in any CouchDB -like database
  • Read it from your $_POST[] server side and retrive a correctly nested array you can then semantically manipulate
  • Use some server-side script to convert it into a well-formed XML file (even if you don't know its exact structure a-priori)
  • Just somehow use it as it is in any Node.js -like server script

OK, so now we need to think how a form can represent an XML file.

Of course the <form> tag is the root , but then we have that <place> element which is a container and not a data element itself, so we cannot use an input tag for it.

Here's where the <fieldset> tag comes in handy! We'll use <fieldset> tags to represent all container elements in our form/XML representation and so getting to a result like this:

<form name="places">

    <fieldset name="place">

        <input type="text" name="name"/>
        <select name="type">
            <option value="dwelling">Dwelling</option>
            <option value="restoration">Restoration</option>
            <option value="sport">Sport</option>
            <option value="administrative">Administrative</option>
        </select>

        <input type="text" name="activity"/>
        <input type="text" name="activity"/>
        <input type="text" name="activity"/>

    </fieldset>

</form>

As you can see in this form, we're breaking the rule of unique names, but this is OK because they'll be converted into an array of element thus they'll be referenced only by their index inside the array.

At this point you can see how there's no name="array[]" like name inside the form and everything is pretty, simple and semantic.

Now we want this form to be converted into a JSON object which will look like this:

{'places':{

    'place':[

        {

            'name': 'Home',
            'type': 'dwelling',

            'activity':[

                 'sleep',
                 'eat',
                 'watch TV'

            ]

        },

        {...},

        {...}

    ]

}}

To do this I have developed this jQuery plugin here which someone helped optimizing in this Code Review thread and looks like this:

$.fn.toJSO = function () {
    var obj = {},
        $kids = $(this).children('[name]');
    if (!$kids.length) {
        return $(this).val();
    }
    $kids.each(function () {
        var $el = $(this),
            name = $el.attr('name');
        if ($el.siblings("[name=" + name + "]").length) {
            if (!/radio|checkbox/i.test($el.attr('type')) || $el.prop('checked')) {
                obj[name] = obj[name] || [];
                obj[name].push($el.toJSO());
            }
        } else {
            obj[name] = $el.toJSO();
        }
    });
    return obj;
};

I also made this one blog post to explain this more.

This converts everything in a form to JSON (even radio and check boxes) and all you'll have left to do is call

$.post('script.php',('form').toJSO(), ...);

I know there's plenty of ways to convert forms into JSON objects and sure .serialize() and .serializeArray() work great in most cases and are mostly intended to be used, but I think this whole idea of writing a form as an XML structure with meaningful names and converting it into a well-formed JSON object is worth the try, also the fact you can add same-name input tags without worrying is very useful if you need to retrive dynamically generated forms data.

I hope this helps someone!


Ich mag es, Array.prototype.reduce weil es ein Array.prototype.reduce ist und nicht auf Underscore.js oder dergleichen beruht:

$('#formid').serializeArray()
    .reduce(function(a, x) { a[x.name] = x.value; return a; }, {});

Dies ähnelt der Antwort mit Array.prototype.map , aber Sie müssen Ihren Bereich nicht mit einer zusätzlichen Objektvariable Array.prototype.map . One-Stop-Shopping.

WICHTIGER HINWEIS : Formulare mit Eingaben, die doppelte Namensattribute aufweisen, sind gültiges HTML und tatsächlich eine allgemeine Vorgehensweise. Die Verwendung einer der Antworten in diesem Thread ist in diesem Fall nicht geeignet (da Objektschlüssel eindeutig sein müssen).


Ok, ich weiß, dass dies bereits eine stark aufgestockte Antwort hat, aber kürzlich wurde eine ähnliche Frage gestellt , und ich wurde auch auf diese Frage hingewiesen. Ich möchte auch meine Lösung anbieten, da sie einen Vorteil gegenüber der akzeptierten Lösung bietet: Sie können deaktivierte Formularelemente einbinden (was manchmal wichtig ist, je nachdem wie Ihre UI-Funktionen funktionieren)

Hier ist meine Antwort von der anderen SO-Frage :

Anfangs verwendeten wir die serializeArray() Methode von jQuery, die jedoch keine deaktivierten Formularelemente enthält. Wir werden häufig Formularelemente deaktivieren, die mit anderen Quellen auf der Seite "synchronisiert" sind, aber wir müssen immer noch die Daten in unser serialisiertes Objekt aufnehmen. Also serializeArray() ist out. Wir haben den :input Selektor verwendet, um alle Eingabeelemente (sowohl aktiviert als auch deaktiviert) in einem gegebenen Container zu erhalten, und dann $.map() , um unser Objekt zu erstellen.

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

Beachten Sie, dass dazu jede Ihrer Eingaben ein Namensattribut benötigt, das den Namen der Eigenschaft des resultierenden Objekts darstellt.

Das ist tatsächlich etwas modifiziert von dem, was wir verwendet haben. Wir mussten ein Objekt erstellen, das als .NET-IDictionary strukturiert war, also haben wir Folgendes verwendet: (Ich stelle es hier zur Verfügung, falls es nützlich ist)

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

Ich mag beide Lösungen, weil sie die $.map() Funktion einfach verwenden und Sie die Kontrolle über Ihren Selektor haben (also, welche Elemente Sie am Ende in Ihr resultierendes Objekt aufnehmen). Außerdem ist kein zusätzliches Plugin erforderlich. Einfaches altes jQuery.


Von einer older Antwort:

$('form input,select').toArray().reduce(function(m,e){m[e.name] = $(e).val(); return m;},{})

Wenn Sie Underscore.js , können Sie das relativ übersichtliche verwenden:

_.object(_.map($('#myform').serializeArray(), _.values))

Wenn Sie versuchen, alle Formularfelder in JSON zu konvertieren, um dieses Formular über Ajax zu senden, hier ist ein jQuery-Formular-Plugin , das das tut.


Verwandle alles in ein Objekt (nicht getestet)

<script type="text/javascript">
string = {};

string.repeat = function(string, count)
{
    return new Array(count+1).join(string);
}

string.count = function(string)
{
    var count = 0;

    for (var i=1; i<arguments.length; i++)
    {
        var results = string.match(new RegExp(arguments[i], 'g'));
        count += results ? results.length : 0;
    }

    return count;
}

array = {};

array.merge = function(arr1, arr2)
{
    for (var i in arr2)
    {
        if (arr1[i] && typeof arr1[i] == 'object' && typeof arr2[i] == 'object')
            arr1[i] = array.merge(arr1[i], arr2[i]);
        else
            arr1[i] = arr2[i]
    }

    return arr1;
}

array.print = function(obj)
{
    var arr = [];
    $.each(obj, function(key, val) {
        var next = key + ": ";
        next += $.isPlainObject(val) ? array.print(val) : val;
        arr.push( next );
      });

    return "{ " +  arr.join(", ") + " }";
}

node = {};

node.objectify = function(node, params)
{
    if (!params)
        params = {};

    if (!params.selector)
        params.selector = "*";

    if (!params.key)
        params.key = "name";

    if (!params.value)
        params.value = "value";

    var o = {};
    var indexes = {};

    $(node).find(params.selector+"["+params.key+"]").each(function()
    {
        var name = $(this).attr(params.key),
            value = $(this).attr(params.value);

        var obj = $.parseJSON("{"+name.replace(/([^\[]*)/, function()
        {
            return '"'+arguments[1]+'"';
        }).replace(/\[(.*?)\]/gi, function()
        {
            if (arguments[1].length == 0)
            {
                var index = arguments[3].substring(0, arguments[2]);
                indexes[index] = indexes[index] !== undefined ? indexes[index]+1 : 0;

                return ':{"'+indexes[index]+'"';
            }
            else
                return ':{"'+escape(arguments[1])+'"';
        })+':"'+value.replace(/[\\"]/gi, function()
        {
            return "\\"+arguments[0]; 
        })+'"'+string.repeat('}', string.count(name, ']'))+"}");

        o = array.merge(o, obj);
    });

    return o;
}
</script>

Die Ausgabe des Tests:

$(document).ready(function()
{
    console.log(array.print(node.objectify($("form"), {})));
    console.log(array.print(node.objectify($("form"), {selector: "select"})));
});

auf

<form>
    <input name='input[a]' type='text' value='text'/>
    <select name='input[b]'>
        <option>select</option>
    </select>

    <input name='otherinput[c][a]' value='a'/>
    <input name='otherinput[c][]' value='b'/>
    <input name='otherinput[d][b]' value='c'/>
    <input name='otherinput[c][]' value='d'/>

    <input type='hidden' name='anotherinput' value='hidden'/>
    <input type='hidden' name='anotherinput' value='1'/>

    <input type='submit' value='submit'/>
</form>

wird ergeben:

{ input: { a: text, b: select }, otherinput: { c: { a: a, 0: b, 1: d }, d: { b: c } }, anotherinput: 1 }
{ input: { b: select } }

Another answer

document.addEventListener("DOMContentLoaded", function() {
  setInterval(function() {
    var form = document.getElementById('form') || document.querySelector('form[name="userprofile"]');
    var json = Array.from(new FormData(form)).map(function(e,i) {this[e[0]]=e[1]; return this;}.bind({}))[0];
    
    console.log(json)
    document.querySelector('#asJSON').value = JSON.stringify(json);
  }, 1000);
})
<form name="userprofile" id="form">
  <p>Name <input type="text" name="firstname" value="John"/></p>
  <p>Family name <input name="lastname" value="Smith"/></p>
  <p>Work <input name="employment[name]" value="inc, Inc."/></p>
  <p>Works since <input name="employment[since]" value="2017" /></p>
  <p>Photo <input type="file" /></p>
  <p>Send <input type="submit" /></p>
</form>

JSON: <textarea id="asJSON"></textarea>

FormData: https://developer.mozilla.org/en-US/docs/Web/API/FormData



I like samuels version, but I believe it has a small error. Normally JSON is sent as

{"coreSKU":"PCGUYJS","name_de":"whatever",...

NOT as

[{"coreSKU":"PCGUYJS"},{"name_de":"whatever"},...

so the function IMO should read:

App.toJson = function( selector ) {
    var o = {};
    $.map( $( selector ), function( n,i )
    {
        o[n.name] = $(n).val();
    });     
    return o;
}

and to wrap it in data array (as commonly expected, too), and finally send it as astring App.stringify( {data:App.toJson( '#cropform :input' )} )

For the stringify look at Question 3593046 for the lean version, at json2.js for the every-eventuality-covered version. That should cover it all :)





serialization