从字符串解析为对象路径

时间:2016-12-18 10:22:41

标签: javascript parsing object

假设我有一个表单,我想检查表单中声明了哪些输入,所以我做了这样的事情:

let inputs = {};

['first_name', 'last_name', ...].forEach(name => {
    let input = document.querySelector(`input[name="${name}"]`);

    if (input !== undefined)
        inputs = Object.assign(inputs, {[input.getAttribute('name')]: input.value});
}

在这种情况下,到目前为止一直很好。

但是如果有一些名为['name.first', 'name.last']的输入怎么办?然后,它会将数据存储到这样的对象:

{name.first: '...', name.last: '...'}.

而不是这样:(这是我想要的结果)

{
    name: {
        first: '...',
        last: '...'
    }
}

如何告诉JavaScript将其解析为对象路径而不是键字符串?

3 个答案:

答案 0 :(得分:1)

我会使用自定义分配功能。

对象可以使用任何字符串作为键,因此“a.b”有效。

以下是assign函数的示例:

function assign(obj, key, value) {
    let keys = key.split(".");
    let last = keys.pop();
    keys.forEach(key => {
        if(!obj[key])
            obj[key] = {};
        obj = obj[key];
    });

    obj[last] = value;
}

let obj = {};
assign(obj, "name.first", "hey");
assign(obj, "name.last", "bye");

console.log(obj);

Bonus recomendation:如果您对所有表单使用相同的格式,则可以将其用作全局表​​单处理程序。

function formHandler(form) {
    let obj = {};
    form.querySelectorAll("input, select").forEach(elem => assign(obj, elem.name, elem.value));
    return obj;
}

答案 1 :(得分:0)

那样的东西?

libswiftCore.dylib`function signature specialization <preserving fragile attribute, Arg[2] = Dead, Arg[3] = Dead> of Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never:
    0x100385174 <+0>:   stp    x26, x25, [sp, #-80]!
    0x100385178 <+4>:   stp    x24, x23, [sp, #16]
    0x10038517c <+8>:   stp    x22, x21, [sp, #32]
    0x100385180 <+12>:  stp    x20, x19, [sp, #48]
    0x100385184 <+16>:  stp    x29, x30, [sp, #64]
    0x100385188 <+20>:  add    x29, sp, #64              ; =64 
    0x10038518c <+24>:  mov    x19, x6
    0x100385190 <+28>:  mov    x20, x5
    0x100385194 <+32>:  mov    x21, x4
    0x100385198 <+36>:  mov    x22, x3
    0x10038519c <+40>:  mov    x23, x2
    0x1003851a0 <+44>:  mov    x24, x1
    0x1003851a4 <+48>:  mov    x25, x0
    0x1003851a8 <+52>:  adr    x8, #936952               ; protocol descriptor for Swift.CVarArg + 88
    0x1003851ac <+56>:  nop    
    0x1003851b0 <+60>:  add    x0, x8, #16               ; =16 
    0x1003851b4 <+64>:  movz   w1, #0x28
    0x1003851b8 <+68>:  orr    w2, wzr, #0x7
    0x1003851bc <+72>:  bl     0x1003854a0               ; rt_swift_allocObject
    0x1003851c0 <+76>:  mov    x8, x0
    0x1003851c4 <+80>:  stp    x22, x21, [x8, #16]
    0x1003851c8 <+84>:  strb   w20, [x8, #32]
    0x1003851cc <+88>:  str    w19, [x8, #36]
    0x1003851d0 <+92>:  adr    x3, #241008               ; partial apply forwarder for Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never).(closure #2)
    0x1003851d4 <+96>:  nop    
    0x1003851d8 <+100>: mov    x0, x25
    0x1003851dc <+104>: mov    x1, x24
    0x1003851e0 <+108>: mov    x2, x23
    0x1003851e4 <+112>: mov    x4, x8
    0x1003851e8 <+116>: bl     0x100278b70               ; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
->  0x1003851ec <+120>: brk    #0x1 //Error message here

答案 2 :(得分:0)

使用与其他答案(拆分,测试和创建)相同的原则来创建路径,但演示了过滤示例的替代方法(如我的评论中所述)。

const wanted = ['name.first', 'name.second', 'name.last'];
const result = Array.from(document.querySelectorAll('input'))
  .filter(input => wanted.includes(input.name))
  .reduce((a, input) => {
    const paths = input.name.split('.');
    const key = paths.pop();
    let current = a;
    paths.forEach(path => current = current[path] ?
      current[path] :
      current[path] = Object.create(null));
    current[key] = input.value;
    return a;
  }, Object.create(null));

console.log(result);
<input name="name.first" value="Eliya" />
<input name="name.middle" value="Wibble" />
<input name="name.last" value="Cohen" />