我如何将条目从HTML5 FormData对象转换为JSON?

解决方案不应该使用jQuery。而且,它不应该简单地序列化整个FormData对象,而应该只序列化它的键/值条目。


当前回答

这篇文章已经有一年了……但是,我真的非常非常喜欢ES6 @dzuc的答案。然而,它是不完整的,不能够处理多个选择或复选框。已经指出了这一点,并提供了代码解决方案。我发现它们很笨重,而且没有优化。所以我写了两个基于@dzuc的版本来处理这些情况:

对于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表单扩展。

Since last time I wrote the previous second case, at work it came a case that the PHP form has checkboxes on multi-levels. I wrote a new case to support previous case and this one. I created a snippet to better showcase this case, the result show on the console for this demo, modify this to your need. Tried to optimize it the best I could without compromising performance, however, it compromise some human readability. It takes advantage that arrays are objects and variables pointing to arrays are kept as reference. No hotshot for this one, be my guest.

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>

其他回答

你可以试试这个

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

下面是一个将formData对象转换为json字符串的函数。

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

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

<select name="select[]" multiple></select>
<input name="check[a][0][]" type="checkbox" value="test"/>

用法:

let json = form2json(formData);

功能:

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

在我的情况下,形式数据是数据,消防基地是期待一个对象,但数据包含对象以及所有其他东西,所以我尝试了数据。珍惜它的作用!!

如果下列物品能满足你的需求,那你就很幸运了:

你想转换一个数组的数组,如[['key','value1'], ['key2','value2'](就像FormData给你的)到一个key->值对象,如{key1: 'value1', key2: 'value2'},并将其转换为JSON字符串。 你的目标浏览器/设备是最新的ES6解释器,或者是用babel之类的东西编译。 你想用最小的方法来完成。

下面是你需要的代码:

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

希望这能帮助到一些人。

如果您正在使用lodash,可以使用fropairs简单地完成

import {fromPairs} from 'lodash';

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