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

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


当前回答

编辑:我看到已经有一个答案得出了非常相似的结果。

两个主要区别:

这不会将数值键作为数组下标,而是将它们视为对象键。可能不是正确的行为,但我个人从来没有写过使用这种符号的表单,可能会更新它。 这不是一个递归函数,这显然不是一个有利或不利的问题

忽略任何缺乏效率的问题。这将处理无限嵌套和数组的重复键。这显然不会转换文件之类的东西,但我不需要它,所以我没有添加它。

下面是一个JSFiddle的转换示例,可以用这个函数实现

一个很好的使用示例(这也是我的用例)是从html表单元素创建一个新的FormData对象,并轻松地将其转换为JSON进行发送。

/**
 * @param {FormData} formData
 * @return {Object}
 */
function formDataToObject(formData) {
    const object = {};
    for (let pair of formData.entries()) {
        const key = pair[0];
        const value = pair[1];
        const isArray = key.endsWith('[]');
        const name = key.substring(0, key.length - (2 * isArray));
        const path = name.replaceAll(']', '');
        const pathParts = path.split('[');
        const partialsCount = pathParts.length;
        let iterationObject = object;
        for (let i = 0; i < partialsCount; i++) {
            let part = pathParts[i];
            let iterationObjectElement = iterationObject[part];
            if (i !== partialsCount - 1) {
                if (!iterationObject.hasOwnProperty(part) || typeof iterationObjectElement !== "object") {
                    iterationObject[part] = {};
                }
                iterationObject = iterationObject[part];
            } else {
                if (isArray) {
                    if (!iterationObject.hasOwnProperty(part)) {
                        iterationObject[part] = [value];
                    } else {
                        iterationObjectElement.push(value);
                    }
                } else {
                    iterationObject[part] = value;
                }
            }
        }
    }

    return object;
}

其他回答

你可以试试这个

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 formData对象中得到你想要的结果的最简单的方法:

const jsonData = {};

for(const [key, value] of formData) {
    jsonData[key] = value;
}

使用JSON.stringify()中描述的toJSON

如果值具有toJSON()方法,则它负责定义将序列化的数据。

这里有一个小技巧。

var fd = new FormData(document.forms[0]); fd.toJSON = function() { const o = {}; this.forEach((v, k) => { v = this.getAll(k); o[k] = v.length == 1 ? v[0] : (v.length >= 1 ? v : null); }); return o; }; document.write(`<pre>${JSON.stringify(fd)}</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>

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

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

import {fromPairs} from 'lodash';

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