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

Leo*_*ela 64 javascript form-data

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

Wil*_*ilt 93

您也可以直接forEachFormData对象上使用:

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

  • 除非需要多重选择等......“JSON.stringify(Object.fromEntries(formData));”的答案要好得多 (9认同)
  • 这不适用于多选表单元素,因为它们共享相同的键,最终会覆盖仅返回最后一个选定元素的值 (3认同)

hak*_*shi 44

在2019年,这种任务变得异常简单。

JSON.stringify(Object.fromEntries(formData));
Run Code Online (Sandbox Code Playgroud)

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

  • 现在是 2020 年,这不处理 `<select multiple>` 或 `<input type="checkbox">` 的多个选定值 (5认同)
  • 最好使用 formData.entries: ```JSON.stringify(Object.fromEntries(formData.entries()));``` (5认同)
  • @Kohver,更好为什么?它会删除重复项吗?它解决了什么样的问题以使其变得更好? (3认同)
  • 来到这里发表这篇文章,喜欢看这个话题,看看这些年来答案如何演变 (2认同)
  • 在具有多个具有相同名称的字段的表单上,这似乎无法正常工作。 (2认同)
  • 我们确定这能正常工作吗?我对同一个键上有多个值的 FormData 进行了尝试,但它只打印了 JSON 字符串中的最后一个值。 (2认同)

dzu*_*zuc 20

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

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

例:

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);
});
Run Code Online (Sandbox Code Playgroud)
<form id='foobar'>
  <input name='baz' />
  <input type='submit' />
</form>

<pre id='output'>Input some value and submit</pre>
Run Code Online (Sandbox Code Playgroud)

  • 我真的很喜欢这个答案,但仍然不处理多个项目。我发布了一个基于这个的新答案来处理这些情况。 (4认同)

Low*_*put 17

到目前为止,我还没有看到任何提及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)
  ])
)
Run Code Online (Sandbox Code Playgroud)

运行中的片段

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>`)
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


som*_*ome 8

如果您有多个具有相同名称的条目,例如,如果您使用<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 );
}
Run Code Online (Sandbox Code Playgroud)

稍微旧的代码(但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 );
  }
Run Code Online (Sandbox Code Playgroud)

  • 但是,当复选框中只有 1 个选中时,该值仍然是单个字符串,而不是数组。 (2认同)

Joy*_*abu 7

如果需要支持序列化嵌套字段,类似于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);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


Gir*_*riB 6

您可以使用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);

});
Run Code Online (Sandbox Code Playgroud)


Car*_*sH. 6

这篇文章已经有一年了……但是,我真的非常喜欢 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);
Run Code Online (Sandbox Code Playgroud)

一行 Hotshot 版本:

Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
Run Code Online (Sandbox Code Playgroud)
  • 对于多个项目名称必须有[]后缀的PHP 样式表单。
Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
Run Code Online (Sandbox Code Playgroud)

一行 Hotshot 版本:

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}),{});
Run Code Online (Sandbox Code Playgroud)
  • 支持多级数组的 PHP 形式的扩展。

自从我上次写前一个案例后,在工作中遇到了一个案例,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);
Run Code Online (Sandbox Code Playgroud)
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}),{});
Run Code Online (Sandbox Code Playgroud)

  • 虽然我很欣赏这种努力 - 像这样的代码是荒谬的。没有人愿意通过字母来查找变量和对象,这不是 1985 年。 (7认同)
  • `Array.from(fd).reduce((obj, [k, v]) =&gt; ({...obj, [k]: v}), {});`热门版本es2018 (2认同)

Ali*_*mal 5

易于使用的功能

为此创造了一个功能

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

    return ConvertedJSON
}
Run Code Online (Sandbox Code Playgroud)

示例用法

var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');)
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我使用for循环创建了空的JSON变量,我key在每个Itration中使用了from formData Object和JSON Keys.

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

  • 这不处理 `&lt;select multiple&gt;` 或 `&lt;input type="checkbox"&gt;` 的多个选定值。 (2认同)

fra*_*iro 5

这是一个将 formData 对象转换为 JSON 字符串的函数。

  • 适用于多个条目和嵌套数组。
  • 适用于编号和命名的输入名称数组。

例如,您可以有以下表单字段:

<select name="select[]" multiple></select>
<input name="check[a][0][]" type="checkbox" value="test"/>
Run Code Online (Sandbox Code Playgroud)

用法:

let json = form2json(formData);
Run Code Online (Sandbox Code Playgroud)

功能:

function form2json(data) {
        
        let method = function (object,pair) {
            
            let keys = pair[0].replace(/\]/g,'').split('[');
            let key = keys[0];
            let value = pair[1];
            
            if (keys.length > 1) {
                
                let i,x,segment;
                let last = value;
                let type = isNaN(keys[1]) ? {} : [];
                
                value = segment = object[key] || type;
                
                for (i = 1; i < keys.length; i++) {
                    
                    x = keys[i];
                    
                    if (i == keys.length-1) {
                        if (Array.isArray(segment)) {
                            segment.push(last);
                        } else {
                            segment[x] = last;
                        }
                    } else if (segment[x] == undefined) {
                        segment[x] = isNaN(keys[i+1]) ? {} : [];
                    }
                    
                    segment = segment[x];
                    
                }
                
            }
            
            object[key] = value;
            
            return object;
            
        }
        
        let object = Array.from(data).reduce(method,{});
        
        return JSON.stringify(object);
        
    }
Run Code Online (Sandbox Code Playgroud)