如何将FormData(HTML5对象)转换为JSON

问题描述 投票:40回答:14

如何将HTML5 FormData对象转换为JSON?没有Jquery并像处理对象一样处理FormData中的嵌套属性。

javascript form-data
14个回答
71
投票

您也可以直接在forEach对象上使用FormData

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

更新:

对于那些喜欢与ES6 arrow functions相同的解决方案的人:

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

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,
  }), {})

1
投票

你可以试试这个

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

1
投票

如果以下项目符合您的需求,那么您很幸运:

  1. 你想将像[['key','value1'], ['key2','value2']这样的数组(就像FormData给你的那样)转换为像{key1: 'value1', key2: 'value2'}这样的key-> value对象并将其转换为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
投票

辱骂一线!

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

今天我学会了firefox有对象传播支持和数组解构!


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

16
投票

这是一种在不使用库的情况下以更实用的方式执行此操作的方法。

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>

8
投票

在2019年,这种任务变得非常容易。

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

Object.fromEntries:Chrome 73+,Firefox 63 +,Safari 12.1支持


7
投票

如果您有多个具有相同名称的条目,例如,如果您使用<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仍然不支持,因为它不支持ForEach上的entriesFormData

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

6
投票

易于使用的功能

我创造了A Function For This

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变量我在每个Itration中使用了formData Object中的keys到JSON Keys。

你在我的JS库中找到这个代码在GitHub上建议我如果它需要改进我已经在这里放置代码https://github.com/alijamal14/Utilities/blob/master/Utilities.js


5
投票

您可以使用FormData()对象来实现此目的。此FormData对象将使用表单的当前键/值填充,使用键的每个元素的name属性及其提交的值。它还将编码文件输入内容。

例:

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

});

5
投票

这篇文章已经有一年了......但是,我真的非常喜欢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>

4
投票

IE11和Safari不支持FormData方法.entriesfor of表达式。

这是一个更简单的版本,支持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在IE11中没有forEach方法。 我仍在寻找支持所有主流浏览器的最终解决方案。


3
投票

如果您使用的是lodash,可以使用fromPairs简洁地完成

import {fromPairs} from 'lodash';

const object = fromPairs(Array.from(formData.entries()));
热门问题
推荐问题
最新问题