是否有更好/更简单的方法将 html 表单序列化为对象

Posted

技术标签:

【中文标题】是否有更好/更简单的方法将 html 表单序列化为对象【英文标题】:Is there a better/simpler way to serializing a html form to an object 【发布时间】:2021-03-24 17:39:30 【问题描述】:

我正在发送一个包含 radiocheckbox 输入的表单(因此多个元素具有相同的名称),这就是我想出的。

有没有更快/更简单的纯 javascript 方法将 html form 转换为 object 以便我可以使用 JSON.stringify

没有框架或库。

function serialize_form(felement) 
    const names = new Set();
    let values = 
    for(let i = 0; i < felement.elements.length; i++) 
        if(felement[i].name && (felement.name != undefined || felement.name != ""))
            names.add(felement[i].name)
        
    

    for(let name of names) 
        values[name] = felement[name].value;
    

   console.log(names, values);

   return values;

【问题讨论】:

在这里查看我对 FormData 的回答:***.com/a/46376650/362536 developer.mozilla.org/en-US/docs/Web/API/FormData @brad 我看到了这个问题,但从未想象过非 jquery 的答案。谢谢。 结合 FormData 和这个answer to how to serialize FormData 是这个问题的答案。 【参考方案1】:

感谢@brad 指出FormData 我能够减少我的serialize_form 函数,这导致了这个答案https://***.com/a/46774073/9908。

function serialize_form(felement) 
            const fd = new FormData(felement);
            let object = ;


            fd.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);
            );
            console.log(object);
            return object;
        

【讨论】:

Object.fromEntries(new FormData(felement))怎么样 @Phil 我刚刚看到了 jQuery 表单问题的答案,我现在正在测试它是否可以处理具有多个值的选择。如果它只是一个班轮,那就太好了。 啊,是的,它在多选或重复名称时失败【参考方案2】:

您可以使用FormData.keys()FormData.getAll() 进行一些简单的转换

document.querySelector("form").addEventListener("submit", e => 
  e.preventDefault()
  
  const fd = new FormData(e.target)
  const obj = Object.fromEntries(Array.from(fd.keys(), key => 
    const val = fd.getAll(key)
    return [ key, val.length > 1 ? val : val.pop() ]
  ))
  
  document.querySelector("pre").innerHTML = JSON.stringify(obj, null, 2)
)
<form>
  <p><input type="text" name="text" value="text value"></p>
  <p>
    Checkboxes:
    <label>Foo <input type="checkbox" value="foo" name="checkbox"></label>
    <label>Bar <input type="checkbox" value="bar" name="checkbox"></label>
    <label>Baz <input type="checkbox" value="baz" name="checkbox"></label>
  </p>
  <p>
    Select:
    <select name="select" multiple>
      <option>foo</option>
      <option>bar</option>
      <option>baz</option>
    </select>
  </p>
  <p><button>Serialize</button></p>
</form>
<pre></pre>

请注意,这会根据选择的次数在数组和字符串之间更改值。如果您想要更一致的 API,即使只有一个选择,也只需为每个值使用数组。

const obj = Object.fromEntries(Array.from(fd.keys(), key => 
  [ key, fd.getAll(key) ]))

【讨论】:

以上是关于是否有更好/更简单的方法将 html 表单序列化为对象的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 序列化为对象

HTML/Javascript 表单 如何将表单数据序列化为 JSON 并在类中显示?

将HTML表单序列化为JavaScript对象,支持嵌套的属性和数组。

将表单数据序列化为 JSON [重复]

使用动态输入将表单数据序列化为 JSON

如何将form内的表单序列化为json字符串