jQuery를 사용하여 양식 데이터를 JavaScript 객체로 변환


1624

양식의 모든 요소를 ​​JavaScript 객체로 어떻게 변환합니까?

각 요소를 반복하지 않고도 양식에서 JavaScript 객체를 자동으로 작성하는 방법을 원합니다. 에서 반환 한 문자열을 원하지 $('#formid').serialize();않거나 맵을 반환하지 않습니다.$('#formid').serializeArray();


16
첫 번째는 GET 메소드를 사용하여 양식을 제출했을 때 얻는 것과 똑같이 문자열을 반환하고 두 번째는 각각 이름 값 쌍을 가진 객체 배열을 제공하기 때문입니다. "email"이라는 필드가 있으면 obj.email로 해당 값을 검색 할 수있는 객체가 필요합니다. serializeArray ()를 사용하면 obj [indexOfElement] .value와 같은 작업을 수행해야합니다.
Yisroel

2
@James-D. Crockford의 JSON-js 라이브러리를 사용하여 허용되는 답변. 예를 들면 다음과 같습니다. github.com/tleese22/google-app-engine-jappstart/blob/master/src/…
Taylor Leese

4
: '(. myForm을') serializeObject () 예 @Taylor, 나는 정답은 크록 포드의 lib 디렉토리와 토비아스 JSON.stringify $ () 그래서 같은 기능을 '사용 말하고 싶지만
제임스 매코맥

5
@Jonz-양식 요소를 사용하는 제출 / 전송 외에 다른 이유가 있습니다. JavaScript 내에서 양식 값 (예 : 단일 페이지 앱)으로 많은 작업을 수행하는 경우 액세스 및 조작을 위해 객체 형식으로 작성하는 것이 매우 편리합니다. 또한 HTTP Post 및 Get 쿼리 문자열이 데이터 이동을위한 유일한 형식은 아닙니다.
Patrick M

3
좋은의 JS 나는 >>에서 온 github.com/marioizquierdo/jquery.serializeJSON
기억 만

답변:


1657

serializeArray이미 정확히 그렇게합니다. 필요한 형식으로 데이터를 마사지하면됩니다.

function objectifyForm(formArray) {//serialize data function

  var returnArray = {};
  for (var i = 0; i < formArray.length; i++){
    returnArray[formArray[i]['name']] = formArray[i]['value'];
  }
  return returnArray;
}

실제 입력과 동일한 이름을 가진 숨겨진 필드를 덮어 씁니다.


4
tvanfosson이 말한 것처럼 왜 컬렉션을 두 번 반복합니까?
Yisroel

69
"serializeArray를 사용하여 처음에 데이터를 얻는 이유는 무엇입니까?" serializeArray가 이미 작성되었으므로 여러 브라우저에서 단위 테스트를 거쳤으며 이후 버전의 jQuery에서 이론적으로 개선 될 수 있습니다. DOM 요소와 같은 일관되지 않은 항목에 직접 액세스해야하는 코드가 적을수록 코드가 더 안정적입니다.
Tobias Cohen

56
serializeArray ()에는 비활성화 된 요소가 포함되지 않습니다. 종종 페이지의 다른 요소와 동기화되는 입력 요소를 비활성화하지만 여전히 직렬화 된 객체에 포함시키기를 원합니다. $.map( $("#container :input"), function(n, i) { /* n.name and $(n).val() */ } );비활성화 된 요소를 포함 해야하는 경우 와 같은 것을 사용하는 것이 좋습니다 .
Samuel Meacham

22
@TobiasCohen foo[bar]다른 입력 이름 종류는 말할 것도없고 예상대로 형식 입력을 처리하지 않습니다 . 이 문제에 대한 얕은 해결책에 매우 좌절 한 후, 나는 내 자신의 jQuery 플러그인을 작성하게되었습니다.
maček

6
@macek 나는 이것이 몇 개월 된 것을 알고 있지만 언제 배열이 숫자가 아닌 인덱스를 사용 했습니까? 아무도 입력 이름을 foo [bar]로 지정해서는 안되며 배열로 취급하기를 바랍니다. 배열과 해시를 혼동하고 있습니까? 그렇습니다. []는 일반적으로 배열만을위한 것이 아니라 접근 자로 이해됩니다. 또한 유효한 HTML이지만 HTML 사양에는 맞지 않는다는 말은 모순입니다. 그렇습니다. 브라우저는 질식하지 않을 수도 있지만 많은 웹 서버는 배열처럼 직렬화를 해제하는 방법을 알지 못합니다. 왜? HTML 사양에 없기 때문입니다. 따라서 실제로 유효하지 않습니다.
kroehre

446

보스처럼 양식을 JSON으로 변환


현재 소스는 GitHubBower에 있습니다.

$ bower 설치 jquery-serialize-object


다음 코드는 더 이상 사용되지 않습니다 .

다음 코드는 모든 종류의 입력 이름으로 작동 할 수 있습니다. 예상대로 처리하십시오.

예를 들면 다음과 같습니다.

<!-- 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"
          }
        }
      }
    }
  }
}

용법

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

마법 (자바 스크립트)

(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);

17
그래서 그것은 꽤 잘 작동합니다. 그러나 이름이 잘못되었으므로 이름에서 알 수 있듯이 JSON을 반환하지 않습니다. 대신 객체 리터럴을 반환합니다. 또한 hasOwnProperty를 확인하는 것이 중요합니다. 그렇지 않으면 배열에 프로토 타입에 첨부 된 항목이 있습니다. {numbers : [ "1", "3", indexOf : function () {...}]}
frontendbeauty

5
@frontendbeauty, 실제로 toJSON은 스펙이 호출 해야하는 것과 정확히 동일합니다. developer.mozilla.org/en/JSON#toJSON()_method 불행한 잘못된 이름.
Ryan Florence

4
@Marek, jsfiddle에서 여기에 대한 테스트를 수행 했습니다 . 트릭은 선택의 이름을 올바르게 지정하는 것입니다. <select name="foo" multiple="multiple">어떤 시나리오에서도 작동하지 않습니다. 그러나 []에서 <select name="bar[]" multiple="multiple">
같이을 사용

3
지적 구함 github.com/serbanghita/formToObject이 같은 일을 유사한 자바 스크립트 방법 (필요 없음 제 3 자 라이브러리)입니다. 'multiple'을 지원하고 'disabled'요소를 무시합니다.
Șerban Ghiță

8
이 솔루션은 폼 요소 이름으로 중첩 키 문제를 처리하므로 맨 위에 있어야합니다.
SquareCat

283

무엇이 잘못 되었나요?

var data = {};
$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 

2
@LayZee-아무것도 선택하지 않으면 왜 백엔드에서 원하십니까? 옵션을 선택해야하는 경우 직렬화하기 전에 입력을 확인하십시오.
치매

21
당신이 아무것도 반환하지 않는 경우에, 당신은 왜 .each대신에 대신 사용 하지 .map않습니까 ??
azerafati

10
그것은 매우 순진하기 때문에 너무 간단합니다 ... 같은 이름의 확인란을 처리하지 않습니다. 매번 확인 된 항목보다 우선합니다. 올바르게 직렬화하려면 입력 유형 감지가 필요합니다.
Joshua F. Rountree

5
순수한 jQuery 솔루션을 원한다면var form = {}; $.each($(this).serializeArray(), function (i, field) { form[field.name] = field.value || ""; });
tfmontague

42
$(this).serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {})
사이트

103

Tobias Cohen 솔루션의 고정 버전. 이 사람은 정확하게 같은 falsy 값 처리 0''.

jQuery.fn.serializeObject = function() {
  var arrayData, objectData;
  arrayData = this.serializeArray();
  objectData = {};

  $.each(arrayData, function() {
    var value;

    if (this.value != null) {
      value = this.value;
    } else {
      value = '';
    }

    if (objectData[this.name] != null) {
      if (!objectData[this.name].push) {
        objectData[this.name] = [objectData[this.name]];
      }

      objectData[this.name].push(value);
    } else {
      objectData[this.name] = value;
    }
  });

  return objectData;
};

코딩 편의성을위한 CoffeeScript 버전 :

jQuery.fn.serializeObject = ->
  arrayData = @serializeArray()
  objectData = {}

  $.each arrayData, ->
    if @value?
      value = @value
    else
      value = ''

    if objectData[@name]?
      unless objectData[@name].push
        objectData[@name] = [objectData[@name]]

      objectData[@name].push value
    else
      objectData[@name] = value

  return objectData

커피 스크립트에서 첫 번째 if 블록을 단축 할 수 있습니다value = @value ? ''
nzifnab

그리고 Rails와 같은 양식을 직렬화하려는 경우 생성 된 키에서 요소 루트를 제거 할 수 있습니다. 이를 위해 새로운 매개 변수 keyMap와 다음 줄을 추가했습니다 key = if keyMap? then keyMap(@name) else @name. 이제와 같은 매핑 기능을 전달할 수 있습니다 (name) -> name.match(/\[([^\]]+)]/)[1]. 그리고 한 이후의 모든 변경해야합니다 @namekey물론
미르 Zekić에게

@ DamirZekić, 루트 요소가 있다면 post간단하게 할 수 $('form').serializeObject().post있습니다. 멋진 매핑이 필요하지 않습니다.
maček

@ DamirZekić이 라인은 무엇을하고 있습니까? if (!objectData[this.name].push)??
kittu 2016 년

@kittu objectData[this.name]푸시 방법이 있는지 확인하고 있습니다 (대략 배열 입니까 ). 배열이면 값을 푸시하고 배열이 아닌 경우 동일한 키를 가진 여러 값이 배열에 결합되도록 배열로 변환합니다.
Daniel X Moore

63

나는 Array.prototype.reduce하나의 라이너이기 때문에 사용하는 것을 좋아 하며 Underscore.js 등에 의존하지 않습니다 .

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

이것은을 사용하는 답변과 비슷 Array.prototype.map하지만 추가 객체 변수로 범위를 어지럽 힐 필요는 없습니다. 원 스톱 쇼핑.

중요 사항 : name속성이 중복 된 입력이있는 양식 은 유효한 HTML이며 실제로는 일반적인 접근 방식입니다. 이 경우 스레드에서 답을 사용하는 것은 부적절합니다 (객체 키가 고유해야하기 때문에).


이것은 매우 우아합니다. 그러나 array.prototype.reduce()ECMAScript 5 사양의 일부이므로 IE8에서는 사용할 수 없습니다. 따라서 IE8 지원이 필요한 경우 폴리 필 또는 다른 솔루션을 모두 사용하고 싶을 것입니다.
gfullam

3
사실이지만 폴리 필하기에 충분히 쉽습니다. 또한 IE11 Enterprise Mode와의 Microsoft의 훌륭한 작업 덕분에 IE8 두통이 거의 끝났습니다 .IE8을 사용하는 개별 사용자에게는 더 이상 서비스를 제공하지 않지만 IE8을 사용하는 직원이 10,000 명인 조직이 등장 할 때마다 다릅니다. 다행히도 Microsoft는이 문제를 해결하기 위해 노력하고 있습니다.
Ethan Brown

1
IT 담당자는 IE11 Enterprise 모드를 살펴보아야합니다. 최신 브라우저와 IE8 호환 앱을 실행하는 방법을 제공합니다. Microsoft의 현명한 움직임 : howtogeek.com/184634/…
Ethan Brown

30

이 모든 대답은 나에게 너무나 위대해 보였다. 간단하게 말해야 할 것이 있습니다. 모든 양식 입력에 이름 속성이 설정되어 있으면 짐 댄디가 작동합니다.

$('form.myform').submit(function () {
  var $this = $(this)
    , viewArr = $this.serializeArray()
    , view = {};

  for (var i in viewArr) {
    view[viewArr[i].name] = viewArr[i].value;
  }

  //Do stuff with view object here (e.g. JSON.stringify?)
});

4
중첩 된 양식 데이터를 처리하지 않으므로 답변이 더 복잡해집니다.
frontendbeauty

나를 위해 일했다. 키-값 페어 만 저장하면됩니다. string을 지정하고 localStorage 또는 쿠키에 저장하면 멋지게 작동했습니다.
Greg Pettit

23

각 요소를 검사하지 않고는 실제로이를 수행 할 방법이 없습니다. 정말로 알고 싶은 것은 "다른 사람이 이미 양식을 JSON 객체로 변환하는 메소드를 작성 했습니까?"입니다. 다음과 같은 것이 작동해야합니다-POST를 통해 반환되는 양식 요소 만 제공합니다 (이름이 있어야 함). 이것은 테스트되지 않았습니다 .

function formToJSON( selector )
{
     var form = {};
     $(selector).find(':input[name]:enabled').each( function() {
         var self = $(this);
         var name = self.attr('name');
         if (form[name]) {
            form[name] = form[name] + ',' + self.val();
         }
         else {
            form[name] = self.val();
         }
     });

     return form;
}

사실, 나는 나를 위해 이것을하는 플러그인을 좋아합니다. 이름을 갖는 것의 한계는 큰 문제가 아닙니다. 텍스트 영역 및 선택 영역을 포함하여 양식의 모든 필드를 가져 옵니까?
Yisroel

[disabled]를 설명하고 싶은지 확실하지 않지만 전송 / 수령해야한다고 생각하지 않습니다.
meder omuraliev

, 내가 양식 자체를 다루는 게 아니에요 이런 식으로지도를 얻을 수 serializeArray ()를 사용하고 그것을 정상적인 JSON 개체를 변환하려면 위의 유사한 코드를 사용하는 것이 더 간단 수 있습니다
Yisroel

2
serializedArray를 사용하면 작동하지만 기본적으로 컬렉션을 두 번 반복하여 한 번 배열을 생성 한 다음 배열을 반복합니다. 나는 그 필요성을 보지 못했다.
tvanfosson

선택기를 활성화 / 비활성화하도록 조정하겠습니다.
tvanfosson

23

당신이 사용하는 경우 Underscore.js을 당신은 상대적으로 간결을 사용할 수 있습니다 :

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

19

입력 된 이름이 배열과 같은 배열 인 name[key]경우 다음 과 같이 생성되어야한다는 다른 모든 답변에 문제가 있는지 확인했습니다 .

name:{ key : value }


예를 들어 , 아래와 비슷한 HTML 양식이있는 경우 :

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

그러나 아래 JSON과 같이 생성되어야하며 다른 모든 대답과 함께 다음과 같은 객체가 아닙니다. 따라서 누구나 다음 JSON과 같은 것을 가져 오려면 아래 JS 코드를 사용해보십시오.

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

$.fn.getForm2obj = function() {
  var _ = {};
  $.map(this.serializeArray(), function(n) {
    const keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);
    if (keys.length > 1) {
      let tmp = _;
      pop = keys.pop();
      for (let i = 0; i < keys.length, j = keys[i]; i++) {
        tmp[j] = (!tmp[j] ? (pop == '') ? [] : {} : tmp[j]), tmp = tmp[j];
      }
      if (pop == '') tmp = (!Array.isArray(tmp) ? [] : tmp), tmp.push(n.value);
      else tmp[pop] = n.value;
    } else _[keys.pop()] = n.value;
  });
  return _;
}
console.log($('form').getForm2obj());
$('form input').change(function() {
  console.clear();
  console.log($('form').getForm2obj());
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<form>
  <input name="name" value="value">
  <input type="checkbox" name="name1[]" value="1" checked="checked">1
  <input type="checkbox" name="name1[]" value="2">2
  <input type="checkbox" name="name1[]" value="3">3<br>
  <input type="radio" name="gender" value="male" checked="checked">male
  <input type="radio" name="gender" value="female"> female
  <input name="name2[key1]" value="value1">
  <input name="one[another][another_one]" value="value4">
  <input name="name3[1][name]" value="value4">
  <input name="name3[2][name]" value="value4">
  <input name="[]" value="value5">
</form>


이 답변의 경우는 언급 다루 않지만, 체크 박스 같은 경우 [] 또는 한 [서로] [another_one] 적용되지 않습니다
레오나르도 BEAL

1
@LeonardoBeal 난 내 ans를 수정 .. 지금 확인 ..!
Bhavik Hirani

나는 eval이런 방식으로 사용되어서는 안되며 eval, 신뢰할 수없고, 버그가 많고, 성능이 좋지 않으며, 잠재적으로 안전하지 않은 관행을 조장 하기 때문에 이러한 방식으로 사용해서는 안되므로 downvoter입니다.
Jack Giffin

2
이것이 좋은 답변이라는 데 동의하지 않습니다. 답변을 작성할 때 코드를 자명하게 설명하거나 설명하십시오. this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);}짧고 설명이 필요하지 않습니다. 경험이 적은 개발자는 왜 그리고 어떻게 작동하는지 이해하지 않고 이것을 복사합니다.
iRaS

2
@JackGiffin 코드 eval()에서 제거되었으므로 지금 새 코드를 확인하십시오 .
Bhavik Hirani

17

좋아, 나는 이미 고도로 찬성 된 답변을 가지고 있지만 최근에 또 다른 비슷한 질문이 있었고 나는이 질문에 대해서도 지시했다. 허용 된 솔루션보다 이점을 제공하기 때문에 솔루션도 제공하고 싶습니다. 비활성화 된 양식 요소를 포함 할 수 있습니다 (UI 기능에 따라 때로는 중요 함)

다른 SO 질문의 대답은 다음과 같습니다 .

처음에는 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.


6
나는 이것을 프로젝트에서 시도했는데, 이것을 사용하여 map단일 속성을 가진 객체 배열을 생성합니다. 속성을 모두 하나의 객체로 축소하지는 않습니다.
joshperry

16

이 함수는 이름이 같은 여러 요소와 함께 다차원 배열을 처리해야합니다.

나는 지금까지 몇 년 동안 그것을 사용해 왔습니다.

jQuery.fn.serializeJSON=function() {
  var json = {};
  jQuery.map(jQuery(this).serializeArray(), function(n, i) {
    var _ = n.name.indexOf('[');
    if (_ > -1) {
      var o = json;
      _name = n.name.replace(/\]/gi, '').split('[');
      for (var i=0, len=_name.length; i<len; i++) {
        if (i == len-1) {
          if (o[_name[i]]) {
            if (typeof o[_name[i]] == 'string') {
              o[_name[i]] = [o[_name[i]]];
            }
            o[_name[i]].push(n.value);
          }
          else o[_name[i]] = n.value || '';
        }
        else o = o[_name[i]] = o[_name[i]] || {};
      }
    }
    else {
      if (json[n.name] !== undefined) {
        if (!json[n.name].push) {
          json[n.name] = [json[n.name]];
        }
        json[n.name].push(n.value || '');
      }
      else json[n.name] = n.value || '';      
    }
  });
  return json;
};

15

당신은 이것을 할 수 있습니다 :

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

JSON을 참조하십시오 .


14

하나의 라이너 (jQuery 이외의 종속성 없음)는 map메소드 에 전달 된 함수에 고정 객체 바인딩을 사용합니다 .

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

그것은 무엇입니까?

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

프로그레시브 웹 앱에 적합


12

사용하다:

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

산출:

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

7

단순성이 가장 좋습니다. 나는 정규 표현식으로 간단한 문자열 바꾸기를 사용했으며 지금까지 매력처럼 작동했습니다. 나는 정규 표현식 전문가는 아니지만 매우 복잡한 객체를 채울 수도 있습니다.

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

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

7

일부에서 이전의 대답 :

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

내가 알 수있는 것의 차이점은 솔루션이 의존하지 않으므로 serializeArray원하는 입력 (예 : 비활성화 된 입력을 포함 할 수 있음)을 자유롭게 선택할 수 있다는 것입니다. 즉, 이것은 어떤 형식이나 제출 이벤트와도 관련이 없으며, 그 자체로 독립적입니까?
dvtan

링크 된 답변의 유일한 작은 차이점은 인스턴스화하는 데 필요한 데이터가 없다는 것입니다 reduce. 개체를 반환합니다. toArrayjQuery 와는 독립적이므로 독립적이지 않습니다 .
사이트

6

Tobias Cohen의 코드에 문제가 있음을 발견했습니다 (직접적으로 언급할만한 충분한 포인트가 없습니다). 값이 ""인 이름이 동일한 두 개의 선택 옵션이있는 경우 원래 코드는 "name": [ "", ""] 대신 "name": ""을 생성합니다.

첫 번째 if 조건에 "|| o [this.name] == ''"을 추가하여이 문제를 해결할 수 있다고 생각합니다.

$.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;
};

6

maček의 솔루션을 사용하여 ASP.NET MVC가 중첩 / 복잡한 객체를 동일한 형식으로 처리하는 방식으로 작동하도록 수정했습니다. 유효성 검사 부분을 다음과 같이 수정하기 만하면됩니다.

"validate": /^[a-zA-Z][a-zA-Z0-9_]*((?:\[(?:\d*|[a-zA-Z0-9_]+)\])*(?:\.)[a-zA-Z][a-zA-Z0-9_]*)*$/,

이것은 다음과 같은 이름을 가진 요소를 일치시키고 올바르게 매핑합니다.

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

<input type="text" name="zooAnimals[0].name" />

5

나는이 문제에 대해있는 가장 간단하고 정확한 방법은 사용하는 것이 었습니다 바베큐 플러그인 또는이 하나 (0.5K의 크기가 바이트에 관한 것입니다).

다차원 배열에서도 작동합니다.

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


이것은 잘 작동하는 것 같습니다. 거기 JQuery와-deparam에 대한 대안 저장소 이물과 NPM에 대한 설명 파일이 포함되어 있습니다.
Alf Eaton


4
const formData = new FormData(form);

let formDataJSON = {};

for (const [key, value] of formData.entries()) {

    formDataJSON[key] = value;
}

3

나는이 접근법을 선호하기 때문에 : 2 개 이상의 컬렉션을 반복 할 필요가없고, 필요한 경우 "이름"과 "값"이외의 것을 얻을 수 있으며, 객체에 저장하기 전에 값을 위생 처리 할 수 ​​있습니다 ( 예를 들어 저장하지 않으려는 기본값이있는 경우).

$.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;
}

다음과 같이 사용하십시오.

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

Firefox에서만 테스트되었습니다.


3

어떤 물체를 물체로 바꾸십시오 (단위 검사되지 않음)

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

테스트 결과 :

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

의 위에

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

산출 할 것이다 :

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

3

선택한 솔루션에 문제가 있습니다.

배열 기반 이름을 가진 양식을 사용할 때 jQuery serializeArray () 함수는 실제로 죽습니다.

배열 기반 필드 이름을 사용하여 동일한 양식을 여러 페이지에서 같은 페이지에 여러 번 넣을 수있는 PHP 프레임 워크가 있습니다. 이는 양식 모델과 충돌하지 않고 동일한 페이지에서 추가, 편집 및 삭제를 모두 수행하는 데 편리 할 수 ​​있습니다.

이 절대 기본 기능을 사용하지 않고 양식을 순화하고 싶었으므로 자체 seralizeArray ()를 작성하기로 결정했습니다.

        var $vals = {};

        $("#video_edit_form input").each(function(i){
            var name = $(this).attr("name").replace(/editSingleForm\[/i, '');

            name = name.replace(/\]/i, '');

            switch($(this).attr("type")){
                case "text":
                    $vals[name] = $(this).val();
                    break;
                case "checkbox":
                    if($(this).attr("checked")){
                        $vals[name] = $(this).val();
                    }
                    break;
                case "radio":
                    if($(this).attr("checked")){
                        $vals[name] = $(this).val();
                    }
                    break;
                default:
                    break;
            }
        });

참고 : 이것은 submit () 형식 외부에서도 작동하므로 나머지 코드에서 오류가 발생하면 링크 변경 버튼에 "변경 사항 저장"이라고 표시하면 양식이 제출되지 않습니다.

또한이 기능을 사용하여 유효성을 검사하기 위해 서버 측으로 전송할 데이터를 수집하기위한 양식의 유효성을 검증해서는 안됩니다. 약하고 대량 할당 된 코드를 사용하면 XSS 등이 발생합니다 .


3

나는 최근에 같은 문제가 있었고 양식을 동일한 구조의 JSON 객체로 변환하는 .toJSON jQuery 플러그인 을 사용했습니다. 또한 사용자가 특정 위치에 더 많은 필드를 추가 할 수 있도록 동적으로 생성 된 양식에 특히 유용합니다.

요점은 실제로 구조 자체를 갖도록 양식을 작성하고 싶을 수 있으므로 사용자가 자신이 좋아하는 장소를 도시에 삽입하는 양식을 만들고 싶다고 가정 해 봅시다 <places>...</places>. 사용자가 좋아하는 장소 목록 따라서 <place>...</place>각 요소마다 <name>...</name>요소, <type>...</type>요소 및 <activity>...</activity>요소 목록을 포함하는 요소 목록은 이러한 장소에서 수행 할 수있는 활동을 나타냅니다. 따라서 XML 구조는 다음과 같습니다.

<places>

    <place>

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

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

    </place>

    <place>...</place>

    <place>...</place>

</places>

이 정확한 구조를 나타내는 JSON 객체를 사용하는 것이 얼마나 멋지므로 다음 중 하나를 수행 할 수 있습니다.

  • 이 개체를 CouchDB 와 같은 데이터베이스에 그대로 저장
  • $ _POST [] 서버 측에서 읽고 올바르게 중첩 된 배열을 검색하여 의미 적으로 조작 할 수 있습니다.
  • 서버 측 스크립트를 사용하여 올바른 형식의 XML 파일로 변환하십시오 (정확한 구조를 모르는 경우에도)
  • Node.js 와 같은 서버 스크립트에서와 같이 어떻게 든 사용하십시오.

이제 폼이 XML 파일을 어떻게 표현할 수 있는지 생각해야합니다.

물론 <form>태그는 root이지만 <place>데이터 요소가 아닌 컨테이너 인 요소가 있으므로 입력 태그를 사용할 수 없습니다.

<fieldset>태그가 유용한 곳이 여기 있습니다 ! <fieldset>태그를 사용 하여 양식 / XML 표현의 모든 컨테이너 요소를 나타내므로 다음과 같은 결과를 얻습니다.

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

이 양식에서 볼 수 있듯이 고유 이름 규칙을 위반하고 있지만 요소 배열로 변환되므로 배열 내부의 인덱스로만 참조되기 때문에 괜찮습니다.

이 시점 name="array[]"에서 폼 안에 이름 이없는 방법을 알 수 있으며 모든 것이 예쁘고 단순하며 의미가 있습니다.

이제이 양식을 다음과 같은 JSON 객체로 변환하려고합니다.

{'places':{

    'place':[

        {

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

            'activity':[

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

            ]

        },

        {...},

        {...}

    ]

}}

이를 위해 누군가이 코드 검토 스레드 에서 최적화하는 데 도움 이되는 다음과 같은 jQuery 플러그인 을 개발 했습니다.

$.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;
};

나는 이것을 더 자세히 설명하기 위해이 블로그 게시물 을 만들었습니다 .

이것은 양식의 모든 것을 JSON (라디오 및 확인란조차)으로 변환하며 전화해야 할 것은 전화입니다.

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

나는 많은 방법이 JSON 객체를하고 있는지에 변환 형태가 알고 .serialize()그리고 .serializeArray()대부분의 경우 작업 크고 주로 사용하기위한 것입니다,하지만 난이 모든 아이디어를 생각하는 의미있는 이름을 가진 XML 구조로 양식을 작성하고로 변환을 잘 구성된 JSON 객체 는 시도해 볼 가치가 있으며, 동적으로 생성 된 양식 데이터를 검색해야하는 경우 걱정없이 동일한 이름의 입력 태그를 추가 할 수 있다는 사실은 매우 유용합니다.

나는 이것이 누군가를 돕기를 바랍니다!


무엇을하려고합니까?
Onheiron


3

또 다른 대답

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


3

[업데이트 2020]

바닐라 js에 간단한 oneliner가 있습니다.

Object.fromEntries(new FormData(form))

2

나는 사무엘 버전을 좋아하지만 작은 오류가 있다고 생각합니다. 일반적으로 JSON은

{ "coreSKU": "PCGUYJS", "name_de": "무엇이든", ...

하지

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

따라서 IMO 기능은 다음과 같아야합니다.

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

그리고 데이터 배열로 감싸고 (일반적으로 예상되는 것처럼) 마지막으로 astring App.stringify ({data : App.toJson ( '#cropform : input')})

stringify 는 린 버전의 질문 3593046 , 모든 이벤트 적용 버전의 json2.js 를 참조하십시오. 그것은 모든 것을 포함해야합니다 :)


감사합니다 .. 이것은 언급했듯이 아주 작지만 중요한 차이를 만듭니다.
Adarsha

2

빠르고 현대적인 솔루션을 얻으 려면 JSONify jQuery 플러그인을 사용하십시오 . 아래 예제는 GitHub README에서 그대로 사용됩니다. 플러그인 작성자 인 Kushal Pandya의 모든 크레딧.

주어진:

<form id="myform">
    <label>Name:</label>
    <input type="text" name="name"/>
    <label>Email</label>
    <input type="text" name="email"/>
    <label>Password</label>
    <input type="password" name="password"/>
</form>

달리는:

$('#myform').jsonify();

생산 :

{"name":"Joe User","email":"joe@example.com","password":"mypass"}

이 JSON 객체로 jQuery POST를 수행하려면 다음을 수행하십시오.

$('#mybutton').click(function() {
    $.post('/api/user', JSON.stringify($('#myform').jsonify()));
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.