使用 javascript 或 jquery 将 Html 非表单数据转换为 JSON

问题描述

我知道我可以使用 jquery.serialize() 将表单数据序列化为 json,但我不想使用它,因为我不想使用一堆隐藏字段并将我的代码包装到表单元素中。

第 1 步我有 mvc 项目,我从我的模型构建了 html,并将名称属性分配给所有元素,所以我最终是这样的:

<div>
<label name="Name">BMW</label>
<label name="Year">2020</label>
<label name="Owner.Id">4</label>
<label name="Owner.Name">John</label>
<label name="Users[0].Id">1</label>
<label name="Users[0].Name">Alex</label>
<label name="Users[0].Licences[0].Id">3</label>
<label name="Users[0].Licences[0].Name">Driving</label>
<label name="Users[1].Id">2</label>
<label name="Users[1].Name">Donald</label>
</div>

当我将表单发布到控制器时,ModelBinder 可以读取它并且它可以工作。 但同样 - 这在我使用隐藏字段和表单元素时有效。我不想这样做。

第 2 步:我制作了自己的序列化程序,它读取所有名称属性并创建 json 对象。 结果如下:

{
    "Name": "BMW","Year": 2020,"Owner.Id" : 4,"Owner.Name" : "John","Users[0].Id" :1,"Users[0].name" : "Alex","Users[0].Licences[0].Id" : 3
    "Users[0].Licences[0].Name" : "Driving"
    "Users[1].Id" : 2,"Users[1].name" : "Donald"
}

问题:如何将此结果转换为 json 对象? 我想要这样的东西:

{
"Name": "BMW","Owner": {
    "Id" : 4,"Name": "John",},"Users":[
    {
        "Id" : 1,"Name" : "Alex","Licences":[
            {
                "Id" : 3,"Name" : "Driving",}
        ]
    },{
        "Id" : 2,"Name" : "Donald"
    }       
]
}

解决方法

如果您想在获得 name-text 键值对的对象后创建自己的解析器,您可以将这些键分割在点和方括号上,然后使用 reduce 方法构建所需的结构。

const result = Array
  .from($('div label'))
  .reduce((o,e) => {
    const key = e
      .getAttribute('name')
      .split(/[\[(.*?)\]|\.]/)
      .filter(Boolean)

    key.reduce((r,k,i,arr) => {
      if (!arr[i + 1]) r[k] = e.textContent;
      else if (!isNaN(+arr[i + 1])) return r[k] = r[k] || []
      else if (!isNaN(+k)) return r[k] = r[k] || {}
      return r
    },o)

    return o;
  },{})

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <label name="Name">BMW</label>
  <label name="Year">2020</label>
  <label name="Owner.Id">4</label>
  <label name="Owner.Name">John</label>
  <label name="Users[0].Id">1</label>
  <label name="Users[0].Name">Alex</label>
  <label name="Users[0].Licences[0].Id">3</label>
  <label name="Users[0].Licences[0].Name">Driving</label>
  <label name="Users[1].Id">2</label>
  <label name="Users[1].Name">Donald</label>
</div>

,

您可以使用 lodash 助手来实现您的目标。

使用灭菌器后的一个非常粗略的例子,您可以通过这种方式应用设置


const values = {
  "Name": "BMW","Year": 2020,"Owner.Id" : 4,"Owner.Name" : "John","Users[0].Id" :1,"Users[0].name" : "Alex","Users[0].Licences[0].Id" : 3,"Users[0].Licences[0].Name" : "Driving","Users[1].Id" : 2,"Users[1].name" : "Donald"
}

const resultObj = {};

Object.keys(values).forEach(key => {
  set(resultObj,key,values[key])
})

在上面的示例中,我们将值设置为 resultObj 变量。