FormData (HTML5 Object)를 JSON으로 변환하는 방법


112

HTML5 FormData 객체를 JSON으로 변환하는 방법은 무엇입니까? Jquery없이 FormData의 중첩 된 속성을 객체처럼 처리합니다.


2
무엇을하려고합니까? 합니까는 JSON.stringify()데 도움이? 다른 방법으로 수행 할 수있는 문제를 해결하려고 할 수 있습니까?
Justinas


3
내가 JSON으로 자바 스크립트 객체를 변환하고 싶지 않기 때문에 중복도 내가 Jquery.serialize ()를 사용 하시겠습니까 아니다
레오나르도 Villela

답변:


157

당신은 또한 사용할 수있는 forEachFormData직접 객체 :

var object = {};
formData.forEach(function(value, key){
    object[key] = value;
});
var json = JSON.stringify(object);

최신 정보:

ES6 화살표 기능 과 동일한 솔루션을 선호하는 사람들을 위해 :

var object = {};
formData.forEach((value, key) => object[key] = value);
var json = JSON.stringify(object);

업데이트 2 :

그리고 다중 선택 목록 또는 여러 값을 가진 다른 양식 요소에 대한 지원을 원하는 사람들을 위해 (이 문제에 대한 답변 아래에 너무 많은 주석이 있기 때문에 가능한 해결책을 추가 할 것입니다) :

var object = {};
formData.forEach((value, key) => {
    // Reflect.has in favor of: object.hasOwnProperty(key)
    if(!Reflect.has(object, key)){
        object[key] = value;
        return;
    }
    if(!Array.isArray(object[key])){
        object[key] = [object[key]];    
    }
    object[key].push(value);
});
var json = JSON.stringify(object);

여기 간단한 다중 선택 목록과 함께이 방법의 사용을 보여주는 Fiddle 이 있습니다.

업데이트 3 :

여기서 끝나는 사람들에 대한 부수적으로, 양식 데이터를 json으로 변환하는 목적이 XML HTTP 요청을 통해 서버로 보내는 FormData것이라면 변환하지 않고 직접 객체를 보낼 수 있습니다 . 다음과 같이 간단합니다.

var request = new XMLHttpRequest();
request.open("POST", "http://example.com/submitform.php");
request.send(formData);

참조 를 위해 MDN에서 FormData 객체 사용 을 참조하십시오 .

업데이트 4 :

내 답변 아래의 주석 중 하나에서 언급했듯이 JSON stringify메서드는 모든 유형의 개체에 대해 즉시 작동하지 않습니다. 지원되는 유형에 대한 자세한 내용 은의 MDN 설명서에서 설명 섹션JSON.stringify 을 참조하고 싶습니다 .

설명에서 다음과 같이 언급됩니다.

값에 toJSON () 메서드가있는 경우 직렬화 할 데이터를 정의해야합니다.

즉, toJSON사용자 지정 개체를 직렬화하는 논리와 함께 고유 한 직렬화 메서드를 제공 할 수 있습니다 . 이와 같이보다 복잡한 개체 트리에 대한 직렬화 지원을 빠르고 쉽게 구축 할 수 있습니다.


1
@TomasPrado의 답변에서 언급했듯이 IE11에 대한 지원이 필요하지 않은지 확인하십시오.
Wilt

4
마지막으로 선택한 요소 만 반환하는 값을 덮어 쓰는 동일한 키를 공유하기 때문에 다중 선택 양식 요소에서는 작동하지 않습니다.
Sean

1
@Sean I는 여러 값에 맞는지 대답했다 <SELECT MULTIPLE><INPUT type="checkbox">동일한 이름의 배열에 값을 변환하여.
일부

formData는 시리즈가 아닙니다. 어떻게 반복 할 수 있습니까? 받아 들인 대답이지만 뭔가 놓친 것입니다.
Nuri YILMAZ

4
등 선택 멀티 필요하지 않는 한 ..와 대답은 JSON.stringify(Object.fromEntries(formData));너무 좋네요
톰 Stickel

111

2019 년에는 이런 종류의 작업이 매우 쉬워졌습니다.

JSON.stringify(Object.fromEntries(formData));

Object.fromEntries: Chrome 73+, Firefox 63+, Safari 12.1에서 지원됨


2
사랑이 스레드를보고 답이 년 동안 진화 방법 보는이를 게시하려면 여기를 온
마르신

14
이름이 같은 여러 필드가있는 양식에서 제대로 작동하지 않는 것 같습니다.
JukkaP

3
2020 년이며 이는 <select multiple>또는 <input type="checkbox"> 😞 의 여러 선택된 값을 처리하지 않습니다
일부는

4
formData.entries를 사용하는 것이 더 좋습니다.JSON.stringify(Object.fromEntries(formData.entries()));
Kohver

22

다음은 라이브러리를 사용하지 않고보다 기능적인 스타일로 수행하는 방법입니다.

Array.from(formData.entries()).reduce((memo, pair) => ({
  ...memo,
  [pair[0]]: pair[1],
}), {});

예:

document.getElementById('foobar').addEventListener('submit', (e) => {
  e.preventDefault();

  const formData = new FormData(e.target);
  const data = Array.from(formData.entries()).reduce((memo, pair) => ({
    ...memo,
    [pair[0]]: pair[1],
  }), {});
  document.getElementById('output').innerHTML = JSON.stringify(data);
});
<form id='foobar'>
  <input name='baz' />
  <input type='submit' />
</form>

<pre id='output'>Input some value and submit</pre>


1
여기에 최고의 답변입니다. 감사합니다 :)
Chunky Chunk

4
나는이 답변을 정말 좋아하지만 여전히 여러 항목을 처리하지 않습니다. 나는 그 사건을 처리하기 위해 이것을 기반으로 새로운 답변을 게시했습니다.
CarlosH.

10

예를 들어 같은 이름의 항목이 여러 개있는 경우, 예를 들어 같은 이름의 항목을 여러 개 사용 <SELECT multiple>하거나 가지고있는 경우 <INPUT type="checkbox">이를 처리하고 값의 배열을 만들어야합니다. 그렇지 않으면 마지막으로 선택한 값만 가져옵니다.

다음은 최신 ES6 변형입니다.

function formToJSON( elem ) {
  let output = {};
  new FormData( elem ).forEach(
    ( value, key ) => {
      // Check if property already exist
      if ( Object.prototype.hasOwnProperty.call( output, key ) ) {
        let current = output[ key ];
        if ( !Array.isArray( current ) ) {
          // If it's not an array, convert it to an array.
          current = output[ key ] = [ current ];
        }
        current.push( value ); // Add the new value to the array.
      } else {
        output[ key ] = value;
      }
    }
  );
  return JSON.stringify( output );
}

(이 지원하지 않기 때문에 여전히 IE11에서 지원하지 않는하지만 약간 오래된 코드 ForEachentries에 대한 FormData)

function formToJSON( elem ) {
  var current, entries, item, key, output, value;
  output = {};
  entries = new FormData( elem ).entries();
  // Iterate over values, and assign to item.
  while ( item = entries.next().value )
    {
      // assign to variables to make the code more readable.
      key = item[0];
      value = item[1];
      // Check if key already exist
      if (Object.prototype.hasOwnProperty.call( output, key)) {
        current = output[ key ];
        if ( !Array.isArray( current ) ) {
          // If it's not an array, convert it to an array.
          current = output[ key ] = [ current ];
        }
        current.push( value ); // Add the new value to the array.
      } else {
        output[ key ] = value;
      }
    }
    return JSON.stringify( output );
  }

7

FormData () 객체를 사용하여이를 수행 할 수 있습니다 . 이 FormData 객체는 키에 대한 각 요소의 이름 속성과 값에 대해 제출 된 값을 사용하여 양식의 현재 키 / 값으로 채워집니다. 또한 파일 입력 내용을 인코딩합니다.

예:

var myForm = document.getElementById('myForm');
myForm.addEventListener('submit', function(event)
{
    event.preventDefault();
    var formData = new FormData(myForm),
        result = {};

    for (var entry of formData.entries())
    {
        result[entry[0]] = entry[1];
    }
    result = JSON.stringify(result)
    console.log(result);

});

이것은 json을 생성하지 않습니다
Liam

1
@Liam 양식 요소로 이것을 시도해 보셨습니까? 그리고 왜 JSON 객체를 생성하지 않는지 알려주세요.
GiriB

1
json 객체와 같은 것은 없습니다. JSON은 문자열 표기법
리암

1
@Liam 객체가 생성 된 후에는 JSON.stringify (result)를 사용할 수 있습니다. 그리고 나는 내 대답을 편집했습니다. 확인해주세요. 그리고 반대표를 철회하십시오.
GiriB

1
당신이 ES6를 사용하는 경우 당신은 또한 문의에 대한 더 표현 할 수 있습니다 : for (const [key, value] of formData.entries())
테디 Zetterlund

7

사용하기 쉬운 기능

나는 이것을 위한 기능을 만들었다

function FormDataToJSON(FormElement){    
    var formData = new FormData(FormElement);
    var ConvertedJSON= {};
    for (const [key, value]  of formData.entries())
    {
        ConvertedJSON[key] = value;
    }

    return ConvertedJSON
}

사용 예

var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');)

이 코드에서는 for루프를 사용하여 빈 JSON 변수를 만들었습니다 key. 모든 반복에서 formData 객체에서 JSON 키로 s를 사용 했습니다.

이 코드는 GitHub의 내 JS 라이브러리에서 찾을 수 있습니다. 개선이 필요한 경우 여기에 코드를 배치했습니다 https://github.com/alijamal14/Utilities/blob/master/Utilities.js


1
@zuluk는 감사합니다
Ali Jamal

<select multiple>또는의 여러 선택된 값을 처리하지 않습니다 <input type="checkbox">.
일부

5

이 게시물은 이미 1 년이 지났지 만 ES6 @dzuc 답변이 정말 마음에 듭니다. 그러나 여러 선택 또는 확인란을 처리 할 수 ​​없기 때문에 불완전합니다. 이것은 이미 지적되었고 코드 솔루션이 제공되었습니다. 무겁고 최적화되지 않았습니다. 그래서 이러한 경우를 처리하기 위해 @dzuc를 기반으로 2 가지 버전을 작성했습니다.

  • 여러 항목 이름이 단순하게 반복 될 수있는 ASP 스타일 양식의 경우.
let r=Array.from(fd).reduce(
  (o , [k,v]) => (
     (!o[k])
     ? {...o , [k] : v}
     : {...o , [k] : [...o[k] , v]}
   )
   ,{}
);
let obj=JSON.stringify(r);

한 줄 핫샷 버전 :

Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
  • 여러 항목 이름에 []접미사 가 있어야하는 PHP 스타일 양식의 경우 .
let r=Array.from(fd).reduce(
  (o , [k,v]) => (
    (k.split('[').length>1)
    ? (k=k.split('[')[0]
      , (!o[k])
      ? {...o , [k] : [v]}
      : {...o , [k] : [...o[k] , v ]}
    )
    : {...o , [k] : v}
  )
  ,{}
);
let obj=JSON.stringify(r);

한 줄 핫샷 버전 :

Array.from(fd).reduce((o,[k,v])=>((k.split('[').length>1)?(k=k.split('[')[0],(!o[k])?{...o,[k]:[v]}:{...o,[k]:[...o[k],v]}):{...o,[k]:v}),{});
  • 다단계 배열을 지원하는 PHP 형식의 확장.

지난 두 번째 사례를 작성한 이후로 직장에서 PHP 양식에 여러 수준의 확인란이있는 경우가 발생했습니다. 이전 케이스와이 케이스를 지원하기 위해 새 케이스를 작성했습니다. 이 사례를 더 잘 보여주기 위해 스 니펫을 만들었습니다. 결과는이 데모의 콘솔에 표시되며 필요에 따라 수정합니다. 성능 저하없이 최선을 다해 최적화하려고했지만 사람의 가독성을 떨어 뜨 렸습니다. 배열은 객체이고 배열을 가리키는 변수는 참조로 유지된다는 이점이 있습니다. 이것에 대한 핫샷은 없습니다.

let nosubmit = (e) => {
  e.preventDefault();
  const f = Array.from(new FormData(e.target));
  const obj = f.reduce((o, [k, v]) => {
    let a = v,
      b, i,
      m = k.split('['),
      n = m[0],
      l = m.length;
    if (l > 1) {
      a = b = o[n] || [];
      for (i = 1; i < l; i++) {
        m[i] = (m[i].split(']')[0] || b.length) * 1;
        b = b[m[i]] = ((i + 1) == l) ? v : b[m[i]] || [];
      }
    }
    return { ...o, [n]: a };
  }, {});
  console.log(obj);
}
document.querySelector('#theform').addEventListener('submit', nosubmit, {capture: true});
<h1>Multilevel Form</h1>
<form action="#" method="POST" enctype="multipart/form-data" id="theform">
  <input type="hidden" name="_id" value="93242" />
  <input type="hidden" name="_fid" value="45c0ec96929bc0d39a904ab5c7af70ef" />
  <label>Select:
    <select name="uselect">
      <option value="A">A</option>
      <option value="B">B</option>
      <option value="C">C</option>
    </select>
  </label>
  <br /><br />
  <label>Checkboxes one level:<br/>
    <input name="c1[]" type="checkbox" checked value="1"/>v1 
    <input name="c1[]" type="checkbox" checked value="2"/>v2
    <input name="c1[]" type="checkbox" checked value="3"/>v3
  </label>
  <br /><br />
  <label>Checkboxes two levels:<br/>
    <input name="c2[0][]" type="checkbox" checked value="4"/>0 v4 
    <input name="c2[0][]" type="checkbox" checked value="5"/>0 v5
    <input name="c2[0][]" type="checkbox" checked value="6"/>0 v6
    <br/>
    <input name="c2[1][]" type="checkbox" checked value="7"/>1 v7 
    <input name="c2[1][]" type="checkbox" checked value="8"/>1 v8
    <input name="c2[1][]" type="checkbox" checked value="9"/>1 v9
  </label>
  <br /><br />
  <label>Radios:
    <input type="radio" name="uradio" value="yes">YES
    <input type="radio" name="uradio" checked value="no">NO
  </label>
  <br /><br />
  <input type="submit" value="Submit" />
</form>


2
Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});hotshot 버전 es2018
nackjicholson

1
@nackjicholson 맞습니다. .entries ()와 [k, v] 요소를 생략하면 코드가 간단 해집니다. 이러한 개선 사항을 포함하도록 코드를 다시 작성하겠습니다. 그러나 반복되는 값은 여전히 ​​덮어 씁니다.
CarlosH.

3
노력에 감사하지만 이와 같은 코드는 터무니 없습니다. 아무도 변수와 객체에 대한 문자를보고 싶어하지 않습니다. 이것은 1985 년이 아닙니다.
Tom Stickel

4

FormData 메서드 .entriesfor of표현식 IE11 및 Safari에서 지원되지 않습니다 .

다음은 Safari, Chrome, Firefox 및 Edge를 지원하는 간단한 버전입니다.

function formDataToJSON(formElement) {    
    var formData = new FormData(formElement),
        convertedJSON = {};

    formData.forEach(function(value, key) { 
        convertedJSON[key] = value;
    });

    return convertedJSON;
}

경고 : 이 답변은 IE11에서 작동하지 않습니다.
FormData에는 forEachIE11에 메서드 가 없습니다 .
모든 주요 브라우저를 지원하는 최종 솔루션을 찾고 있습니다.


이것은 완벽 해요! 우리는 이전 브라우저를 지원해야하며 반복기 사용은 그리 직관적이지 않습니다.
Peter Hawkins 17

4

PHP가 양식 필드를 처리하는 방식과 유사한 중첩 필드 직렬화에 대한 지원이 필요한 경우 다음 함수를 사용할 수 있습니다.

function update(data, keys, value) {
  if (keys.length === 0) {
    // Leaf node
    return value;
  }

  let key = keys.shift();
  if (!key) {
    data = data || [];
    if (Array.isArray(data)) {
      key = data.length;
    }
  }

  // Try converting key to a numeric value
  let index = +key;
  if (!isNaN(index)) {
    // We have a numeric index, make data a numeric array
    // This will not work if this is a associative array 
    // with numeric keys
    data = data || [];
    key = index;
  }
  
  // If none of the above matched, we have an associative array
  data = data || {};

  let val = update(data[key], keys, value);
  data[key] = val;

  return data;
}

function serializeForm(form) {
  return Array.from((new FormData(form)).entries())
    .reduce((data, [field, value]) => {
      let [_, prefix, keys] = field.match(/^([^\[]+)((?:\[[^\]]*\])*)/);

      if (keys) {
        keys = Array.from(keys.matchAll(/\[([^\]]*)\]/g), m => m[1]);
        value = update(data[prefix], keys, value);
      }
      data[prefix] = value;
      return data;
    }, {});
}

document.getElementById('output').textContent = JSON.stringify(serializeForm(document.getElementById('form')), null, 2);
<form id="form">
  <input name="field1" value="Field 1">
  <input name="field2[]" value="Field 21">
  <input name="field2[]" value="Field 22">
  <input name="field3[a]" value="Field 3a">
  <input name="field3[b]" value="Field 3b">
  <input name="field3[c]" value="Field 3c">
  <input name="field4[x][a]" value="Field xa">
  <input name="field4[x][b]" value="Field xb">
  <input name="field4[x][c]" value="Field xc">
  <input name="field4[y][a]" value="Field ya">
  <input name="field5[z][0]" value="Field z0">
  <input name="field5[z][]" value="Field z1">
  <input name="field6.z" value="Field 6Z0">
  <input name="field6.z" value="Field 6Z1">
</form>

<h2>Output</h2>
<pre id="output">
</pre>


1
"function update (data, keys, value) {"의 "[]"배열에서 "{}"객체로 "data"의 기본값을 업데이트해야 빈 배열 문제가 제거됩니다.
Chintan Mathukiya

또한 축소하기 전에 배열 필터를 추가하여 최종 개체에서 빈 필드를 제거하는 것이 좋습니다
Ednilson Maia

@ChintanMathukiya Maia 예상치 못한 결과가 나오는 샘플 입력을 공유 할 수 있습니까?
Joyce Babu

@Ednilson 빈 배열 출력이 표시되는 샘플 데이터를 공유 할 수 있습니까?
Joyce Babu

3

lodash를 사용하는 경우 간결하게 수행 할 수 있습니다. fromPairs

import {fromPairs} from 'lodash';

const object = fromPairs(Array.from(formData.entries()));

2

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

formDataToJSON($('#form_example'));

# Create a function to convert the serialize and convert the form data
# to JSON
# @param : $('#form_example');
# @return a JSON Stringify
function formDataToJSON(form) {
    let obj = {};
    let formData = form.serialize();
    let formArray = formData.split("&");

    for (inputData of formArray){
        let dataTmp = inputData.split('=');
        obj[dataTmp[0]] = dataTmp[1];
    }
    return JSON.stringify(obj);
}

2

@dzuc의 대답은 이미 매우 훌륭하지만 배열 분해 (최신 브라우저 또는 Babel에서 사용 가능)를 사용하여 좀 더 우아하게 만들 수 있습니다.

// original version from @dzuc
const data = Array.from(formData.entries())
  .reduce((memo, pair) => ({
    ...memo,
    [pair[0]: pair[1],
  }), {})

// with array destructuring
const data = Array.from(formData.entries())
  .reduce((memo,[key, value]) => ({
    ...memo,
    [key]: value,
  }), {})

2

모욕적 인 한 줄짜리!

Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});

오늘 저는 firefox에 객체 확산 지원과 배열 분해 기능이 있다는 것을 배웠습니다!


1

다음 항목이 귀하의 요구를 충족한다면 운이 좋을 것입니다.

  1. [['key','value1'], ['key2','value2']FormData가 제공하는 것과 같은 배열 배열을 다음과 같은 key-> value 객체로 변환하고 싶습니다.{key1: 'value1', key2: 'value2'} 것으로 변환하고 JSON 문자열로 변환하려고합니다.
  2. 최신 ES6 인터프리터로 브라우저 / 장치를 대상으로하거나 babel과 같은 것으로 컴파일하고 있습니다.
  3. 이 작업을 수행하는 가장 작은 방법을 원합니다.

필요한 코드는 다음과 같습니다.

const data = new FormData(document.querySelector('form'));
const json = JSON.stringify(Array.from(data).reduce((o,[k,v])=>(o[k]=v,o),{}));

이것이 누군가를 돕기를 바랍니다.


1

FormData.getAll에 대한 언급이 없습니다.지금까지 메서드에 .

FormData 객체 내에서 주어진 키와 관련된 모든 값을 반환하는 것 외에도 여기에 다른 사람이 지정한대로 Object.fromEntries 메서드를 사용하면 정말 간단 합니다.

var formData = new FormData(document.forms[0])

var obj = Object.fromEntries(
  Array.from(formData.keys()).map(key => [
    key, formData.getAll(key).length > 1 ? 
      formData.getAll(key) : formData.get(key)
  ])
)

작동중인 스 니펫

var formData = new FormData(document.forms[0])

var obj = Object.fromEntries(Array.from(formData.keys()).map(key => [key, formData.getAll(key).length > 1 ? formData.getAll(key) : formData.get(key)]))

document.write(`<pre>${JSON.stringify(obj)}</pre>`)
<form action="#">
  <input name="name" value="Robinson" />
  <input name="items" value="Vin" />
  <input name="items" value="Fromage" />
  <select name="animals" multiple id="animals">
    <option value="tiger" selected>Tigre</option>
    <option value="turtle" selected>Tortue</option>
    <option value="monkey">Singe</option>
  </select>
</form>


0

나를 위해 일했다

                var myForm = document.getElementById("form");
                var formData = new FormData(myForm),
                obj = {};
                for (var entry of formData.entries()){
                    obj[entry[0]] = entry[1];
                }
                console.log(obj);

<select multiple>또는의 여러 선택된 값을 처리하지 않습니다<input type="checkbox">
일부

0

내 경우에는 Data가 data 였고, fire base는 객체를 기대했지만 데이터에는 객체와 다른 모든 것들이 포함되어 있으므로 data.value를 시도했습니다!


0

여기 늦게 도착합니다. 그러나 입력 유형 = "checkbox"를 확인하는 간단한 방법을 만들었습니다.

var formData = new FormData($form.get(0));
        var objectData = {};
        formData.forEach(function (value, key) {
            var updatedValue = value;
            if ($('input[name="' + key + '"]').attr("type") === "checkbox" && $('input[name="' + key + '"]').is(":checked")) {
                updatedValue = true; // we don't set false due to it is by default on HTML
            }
            objectData[key] = updatedValue;
        });
var jsonData = JSON.stringify(objectData);

다른 사람에게 도움이되기를 바랍니다.


-1

특별한 것을 사용하지 않고도이 일을 쉽게 할 수 있습니다. 아래와 같은 코드로 충분합니다.

var form = $(e.currentTarget);

var formData = objectifyForm(form);


function objectifyForm(formArray) {

    var returnArray = {};
    for (var i = 0; i < formArray[0].length; i++) {
        var name = formArray[0][i]['name'];
        if (name == "") continue;
        if (formArray[0][i]['type'] == "hidden" && returnArray[name] != undefined) continue;
        if ($(formArray[0][i]).attr("type") == "radio") {
            var radioInputs = $("[name='" + name + "']");
            var value = null;
            radioInputs.each(function (radio) {
                if ($(this)[0].checked == true) {
                    value = $(this).attr("id").split("_")[$(this).attr("id").split("_").length - 1];
                }
            });
            returnArray[name] = value;
        }
        else if ($(formArray[0][i]).attr("type") == "checkbox") {
            returnArray[name] = $(formArray[0][i])[0].checked;
        }
        else
            returnArray[name] = formArray[0][i]['value'];
    }



    return returnArray;
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.